3

Hello I would like to parse a js file in bash containing settings in this way :

user_pref("network.proxy.socks", "127.0.0.1");
user_pref("network.proxy.socks_port", 9150);
user_pref("network.proxy.type", 1);
  • if the lines do not exist, it should be created (>>append).
  • if the lines are already set with those values : do nothing.
  • If the lines are already set with different values, change it for values "127.0.0.1", 9150, 1

So far I can perform point 1 and 2, but I struggle on point 3. I believe it can be achieved by using bash conditionals, and 'sed' with a regex pattern. Can anyone (regex guru) help me please ?


Quick introduction to my problem :

I am writing a bash script on OS X and have socks5 listening on 127.0.0.1:9150. I want then to set those settings for Firefox by editing the prefs.js file (equivalent of url about:config). The GUI for this is Preferences/Advanced/Network/Connection Settings/Manual Proxy/Socks5.

FYI, here's my script, the missing part is ###MISSING PART### :

function sshD
{
    pkill firefox #Kill existing instance(s) of Firefox
    #Create HTTP Proxy via SSH Tunnel
    ssh -Cc blowfish -D9150 -Nf myuser@mydomain
    fxpref="$HOME/Library/Application Support/Firefox/Profiles/"; fxpref="$fxpref`ls "$fxpref" | awk 'NR==1'`/prefs.js"
    test ! -f "$fxpref".backup && cp "$fxpref" "$fxpref".backup
    proxypref=`cat "$fxpref" | grep proxy`
    ###MISSING PART###
    /Applications/Firefox.app/Contents/MacOS/firefox-bin -private > /dev/null 2>&1 &
}
mklement0
  • 382,024
  • 64
  • 607
  • 775
Florian Bidabé
  • 640
  • 8
  • 22
  • why can't you over write with the default values always with out performing any check? – Suku Jul 01 '14 at 11:09
  • Because this is point 3, I do not .know how to detect the line and replace it with sed. If I >>append, I end up creating duplicates. – Florian Bidabé Jul 01 '14 at 11:33

2 Answers2

4

A solution that works with FreeBSD sed (OS X) as well as with GNU sed (Linux) - basics of the approach are based on @anishsane's answer:

Note:

  • The assumption is that it's OK to not preserve the original order of preferences in the input file so as to simplify the solution.
  • Thus, this solution effectively first removes existing preferences of interest (if any) from the input file, and then appends them with the desired (new) values to the end.
sed -En '/user_pref\("network\.proxy\.(socks|socks_port|type)"/!p
        $ a\
user_pref("network.proxy.socks", "127.0.0.1");\
user_pref("network.proxy.socks_port", 9150);\
user_pref("network.proxy.type", 1);
        ' prefs.js

Note: The above just outputs the result to stdout; if you wanted to replace the input file with the result, saving the original to *.backup, use:

sed -En -i'.backup' ...

Explanation:

  • -E turns on support for extended regular expressions, which adds crucial features such as | for alternation (aside from needing less escaping).
  • -n suppresses default output of (potentially modified) input lines, so that only explicit output functions such as p, a, and i produce output.
  • /user_pref\("network\.proxy\.(socks|socks_port|type)"/!p causes all lines NOT containing the preferences of interest to be printed; in other words: existing lines containing the preferences of interest (with their current values) are effectively deleted.
  • $ a appends text to the output after the last line ($) of input, and here simply outputs the preferences of interest with the desired new values.
  • Overall, the \-escaped newlines are carefully placed to make FreeBSD sed happy - a pure GNU sed solution would be simpler; see https://stackoverflow.com/a/24276470/45375 for the differences between the two implementations.
Community
  • 1
  • 1
mklement0
  • 382,024
  • 64
  • 607
  • 775
1

I believe that firefox's pref.js is read line-by-line & the sequence of these preferences is not important.

So, this should work:

sed '/user_pref("network.proxy.\(socks\|socks_port\|type\)"/d;
        $auser_pref("network.proxy.socks", "127.0.0.1");\nuser_pref("network.proxy.socks_port", 9150);\nuser_pref("network.proxy.type", 1);' pref.js
anishsane
  • 20,270
  • 5
  • 40
  • 73
  • Thank you anishsane, however the option -r does not exists on "Darwin Kernel Version 13.1.0" (OS X 10.9). man sed -> HISTORY : A sed command, written by L. E. McMahon, appeared in Version 7 AT&T UNIX. BSD May 10, 2005 – Florian Bidabé Jul 01 '14 at 11:40
  • I had added `-r` only to bypass some escaping of `(`, `|` with `\`... Misusing features for own laziness ;) Updated the answer. – anishsane Jul 01 '14 at 12:49
  • On OSX you can use `-E` instead of `-r` (to enable support for _extended_ regexes) (note that `-E` even works with GNU `sed`, though the manual doesn't say so). However: Alternation (`|`) in a _basic_ regex is not part of POSIX, so FreeBSD `sed` only supports alternation with `-E`. There are other things FreeBSD/OSX `sed` doesn't support, such as appending text directly to the `a` function and using `\n` in the text argument - see http://stackoverflow.com/a/24276470/45375 – mklement0 Jul 01 '14 at 13:08
  • Thanks I did indeed have a "error: parentheses not balanced", but I now get a "sed: 1: "/user_pref("network.pro ...": command a expects \ followed by text". I'm sorry if I'n missing something essential. – Florian Bidabé Jul 01 '14 at 13:28
  • FreeBSD/OSX ... OpenBSD/OSX(e.g. pfctl)... Linux...I thought using bash would kind of work both ways for unix/linux kernels/flavours, guess I'm not a developer fella. – Florian Bidabé Jul 01 '14 at 13:35
  • ^^ `bash` & `sed` are independent :-) – anishsane Jul 01 '14 at 13:47
  • `bash` is not in the mix here - only the differing `sed` implementations - there are, sadly, many small differences, which I've attempted to summarize in the linked answer. @FlorianBidabe: The short of it: follow `a` with `\ ` (ignore the space after - needed it for formatting) followed by an _actual_ newline; similarly, replace the `\n` instances with `\ ` followed by an _actual_ newline. (Alternatively, splice `$'\n'` into the string to create newlines). – mklement0 Jul 01 '14 at 13:49
  • Elegant solution - if you fix it to work on OSX, I'll up-vote. – mklement0 Jul 01 '14 at 14:00
  • Right, thanks for your help, I get that the shell(command line interpreter) has nothing to do with a unix utility like sed. You guys are more knowledgeable than I in terms of scripting, if we avoid using sed, since there are different implementations, Can we use something else ? I know vim but this requires manual input, right ? – Florian Bidabé Jul 01 '14 at 14:01
  • <> Guess I'm gonna spend an over sleepless night on this ahah – Florian Bidabé Jul 01 '14 at 14:02
  • On 2nd thought: even with GNU `sed` your answer will only work if the last input line does not match the regex, because the `d` will otherwise prevent the `$a` from getting executed. – mklement0 Jul 01 '14 at 14:28
  • 1
    ^^ That's actually right. Even heuristically, the second time when the script runs, these entries will be at the end. But looks like your answer already has that covered. – anishsane Jul 02 '14 at 05:58