Invalid preceding regex
I receive error:
awk: bad regex '{|:|}': Invalid preceding regular expression {"arguments":{},"result":"success"} {"port":37482}
Which I believe is related to this line:
PORT=$(echo $json | awk 'BEGIN{r=1;FS="{|:|}"} /port/{r=0; print $3} END{exit r}')
#echo $PORTDoes anyone know what it means and how I can fix it? I am new to scripting but as I understand it the expression |:| is incorrect. $json is a file I am pulling from my VPN with port information for forwarding.
My input:
#!/usr/bin/env bash
#
# Enable port forwarding when using Private Internet Access
#
# Usage:
# ./port_forwarding.sh
TRANSUSER=xxx
TRANSPASS=xxxx
TRANSHOST=localhost
error( )
{ echo "$@" 1>&2 exit 1
}
error_and_usage( )
{ echo "$@" 1>&2 usage_and_exit 1
}
usage( )
{ echo "Usage: `dirname $0`/$PROGRAM"
}
usage_and_exit( )
{ usage exit $1
}
version( )
{ echo "$PROGRAM version $VERSION"
}
port_forward_assignment( )
{ client_id_file="/etc/openvpn/pia_client_id" if [ ! -f "$client_id_file" ]; then if hash shasum 2>/dev/null; then head -n 100 /dev/urandom | shasum -a 256 | tr -d " -" > "$client_id_file" elif hash sha256sum 2>/dev/null; then head -n 100 /dev/urandom | sha256sum | tr -d " -" > "$client_id_file" else echo "Please install shasum or sha256sum, and make sure it is visible in your \$PATH" exit 1 fi fi client_id=`cat "$client_id_file"` json=`curl "" 2>/dev/null` if [ "$json" == "" ]; then json='Port forwarding is already activated on this connection, has expired, or you are not connected to a PIA region that supports port forwarding' fi echo $json
}
#trim VPN forwarded port from JSON
PORT=$(echo $json | awk 'BEGIN{r=1;FS="{|:|}"} /port/{r=0; print $3} END{exit r}')
#echo $PORT
#change transmission port on the fly
CURLOUT=$(curl -u $TRANSUSER:$TRANSPASS ${TRANSHOST}:9091/transmission/rpc 2>/dev/null)
REGEX='X-Transmission-Session-Id\: (\w*)'
if [[ $CURLOUT =~ $REGEX ]]; then SESSIONID=${BASH_REMATCH[1]}
else exit 1
fi
DATA='{"method": "session-set", "arguments": { "peer-port" :'$port' } }'
curl -u $TRANSUSER:$TRANSPASS -d "$DATA" -H "X-Transmission-Session-Id: $SESSIONID"
EXITCODE=0
PROGRAM=`basename $0`
VERSION=2.1
while test $# -gt 0
do case $1 in --usage | --help | -h ) usage_and_exit 0 ;; --version | -v ) version exit 0 ;; *) error_and_usage "Unrecognized option: $1" ;; esac shift
done
port_forward_assignment
exit 0The script is taken from: ?
It is designed to make a request to their API for a port number and then to forward that port received into transmission daemon.
32 Answers
If you are asking "How can I get the port number from this input data?", with the following data:
{"arguments":{},"result":"success"} {"port":37482}Then I'd advise you look at jq:
$ echo '{"arguments":{},"result":"success"} {"port":37482}' | jq -s '.[1].port'
37482jq -s will "slurp" the input into an array, this is necessary as you are providing two distinct objects:
$ echo '{"arguments":{},"result":"success"} {"port":37482}' | jq -s '.'
[ { "arguments": {}, "result": "success" }, { "port": 37482 }
]You must then address the second element of the array (.[1]), and subsequently the 'port' element (.[1].port).
As an extension to address some of your further questions:
You do know what the JSON is, you grab it here, and could easily print it, redirect it to a file, etc...
client_id=$(cat "$client_id_file")
curl "" > EXAMPLE.jsonI've identified a method to extract the port number above, but if you can't / don't want to use jq, then python would work nicely, but unfortunately your input appears to be not-quite-JSON, so we need to work a bit harder:
Note: we need to pass the JSON in as the first argument, as the script is going in via stdin, so the echo xxx | jq approach above won't work nicely.
$ python - <<"EOF" '{"arguments":{},"result":"success"} {"port":37482}'
def read_obj(filename): from sys import argv from json import JSONDecoder decoder = JSONDecoder() file_content = argv[1].lstrip() while file_content: obj, eod = decoder.raw_decode(file_content) file_content = file_content[eod:].lstrip() yield obj
x = read_obj('x')
obj = next(x) # discard the first object
obj = next(x) # use the second object
print(obj['port'])
EOFI can't help you interface with transmission.
5Success! Working script below:
Dependencies: transmission-remote - you can install the transmission-remote-openssl package through optware. sha256sum - optware package coreutils-sha256sum
#!/usr/bin/env bash
#
# Enable port forwarding when using Private Internet Access
#
# Usage:
# ./port_forwarding.sh
# script must be run within 2 mins of connecting to vpn server. Do not forget to reconnect/connect
# fill in your transmission username, password and hostname/ip below:
TRANSUSER=xxxxx
TRANSPASS=xxxxx
TRANSHOST=localhost
#now let the script do the work
Sleep 20
echo pausing to wait for vpn to connect and transmission to start
error( )
{ echo "$@" 1>&2 exit 1
}
error_and_usage( )
{ echo "$@" 1>&2 usage_and_exit 1
}
usage( )
{ echo "Usage: `dirname $0`/$PROGRAM"
}
usage_and_exit( )
{ usage exit $1
}
version( )
{ echo "$PROGRAM version $VERSION"
}
port_forward_assignment( )
{ client_id_file="/etc/openvpn/pia_client_id" if [ ! -f "$client_id_file" ]; then if hash shasum 2>/dev/null; then head -n 100 /dev/urandom | shasum -a 256 | tr -d " -" > "$client_id_file" elif hash sha256sum 2>/dev/null; then head -n 100 /dev/urandom | sha256sum | tr -d " -" > "$client_id_file" else echo "Please install shasum or sha256sum, and make sure it is visible in your \$PATH" exit 1 fi fi client_id=`cat "$client_id_file"` json=`curl "" 2>/dev/null` if [ "$json" == "" ]; then json='Port forwarding is already activated on this connection, has expired, or you are not connected to a PIA region that supports port forwarding' fi echo server returned: $json
#trim VPN forwarded port from JSON
PORT=$(echo $json | awk 'BEGIN{r=1;FS="[{}\":]+"} /port/{r=0; print $3} END{exit r}')
echo if successful, trimmed port is:$PORT
#change transmission port on the fly
transmission-remote $TRANSHOST --auth $TRANSUSER:$TRANSPASS -p "$PORT"
echo here are your transmission credentials: host:$TRANSHOST username:$TRANSUSER password:$TRANSPASS
}
echo remember to run no longer than 2 mins after reconnecting/connecting to vpn server.
EXITCODE=0
PROGRAM=`basename $0`
VERSION=2.1
while test $# -gt 0
do case $1 in --usage | --help | -h ) usage_and_exit 0 ;; --version | -v ) version exit 0 ;; *) error_and_usage "Unrecognized option: $1" ;; esac shift
done
port_forward_assignment
exit 0