【问题标题】:Editing few lines of a file in bash在 bash 中编辑文件的几行
【发布时间】:2014-08-21 19:32:52
【问题描述】:

您好,我想以这种方式在 bash 中解析一个包含设置的 js 文件:

user_pref("network.proxy.socks", "127.0.0.1");
user_pref("network.proxy.socks_port", 9150);
user_pref("network.proxy.type", 1);
  • 如果这些行不存在,则应该创建它(>>append)。
  • 如果行已经设置了这些值:什么都不做。
  • 如果线条已经设置了不同的值,请将其更改为值 "127.0.0.1"91501

到目前为止,我可以执行第 1 点和第 2 点,但我在第 3 点上很挣扎。 我相信它可以通过使用 bash 条件和带有正则表达式模式的 'sed' 来实现。 任何人(正则表达式大师)可以帮助我吗?


快速介绍我的问题:

我正在 OS X 上编写一个 bash 脚本,并让 socks5 在 127.0.0.1:9150 上监听。 然后我想通过编辑 prefs.js 文件(相当于 url about:config)为 Firefox 设置这些设置。用于此的 GUI 是 Preferences/Advanced/Network/Connection Settings/Manual Proxy/Socks5

仅供参考,这是我的脚本,缺少的部分是 ###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 &
}

【问题讨论】:

  • 为什么你不能在不执行任何检查的情况下始终使用默认值覆盖?
  • 因为这是第3点,我不知道如何检测该行并用sed替换它。如果我>>追加,我最终会创建重复项。

标签: regex macos sed


【解决方案1】:

适用于 FreeBSD sed (OS X) 以及 GNU sed (Linux) 的解决方案 - 该方法的基础基于 @anishsane's answer

注意:

  • 假设可以在输入文件中保留首选项的原始顺序以简化解决方案。
  • 1234563 结束
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

注意:以上只是将结果输出到stdout;如果您想用结果替换输入文件,将原始文件保存到*.backup,请使用:

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

解释:

  • -E 开启了对扩展正则表达式的支持,这增加了诸如| 之类的重要功能用于交替(除了需要较少的转义)。
  • -n 抑制(可能修改的)输入行的默认输出,以便只有显式输出函数(如 pai)产生输出。
  • /user_pref\("network\.proxy\.(socks|socks_port|type)"/!p 导致打印所有不包含感兴趣的首选项的行;换句话说:包含感兴趣的偏好(及其当前值)的现有行被有效地删除
  • $ a 将文本附加到输入的最后行 ($) 之后的输出,这里只是用所需的值输出感兴趣的首选项。李>
  • 总的来说,\-转义的换行符是精心放置的,以使 FreeBSD sed 满意 - 纯 GNU sed 解决方案会更简单;请参阅 https://stackoverflow.com/a/24276470/45375 了解两种实现之间的差异。

【讨论】:

  • 它现在按预期工作非常感谢您。非常高兴知道如何在 BSD 上使用 sed,再次感谢您!
  • @FlorianBidabe:我的荣幸;我很高兴它对你有用。
【解决方案2】:

我相信 firefox 的 pref.js 是逐行读取的,这些首选项的顺序并不重要。

所以,这应该可行:

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

【讨论】:

  • 谢谢你,但选项 -r 在“Darwin Kernel Version 13.1.0”(OS X 10.9)上不存在。 man sed -> HISTORY :由 L. E. McMahon 编写的 sed 命令出现在版本 7 AT&T UNIX 中。 BSD 2005 年 5 月 10 日
  • 我添加了 -r 只是为了绕过 (| 的一些转义,并带有 ``... 为自己的懒惰而滥用功能 ;) 更新了答案。
  • 在 OSX 上,您可以使用 -E 而不是 -r(启用对 扩展 正则表达式的支持)(请注意,-E 甚至可以与 GNU sed 一起使用,虽然手册没有这么说)。但是:basic 正则表达式中的交替 (|) 不是 POSIX 的一部分,因此 FreeBSD sed 仅支持与 -E 的交替。还有其他一些 FreeBSD/OSX sed 不支持的东西,例如将文本直接附加到 a 函数并在文本参数中使用 \n - 请参阅 stackoverflow.com/a/24276470/45375
  • 谢谢我确实有一个“错误:括号不平衡”,但我现在得到一个“sed:1:”/user_pref(“network.pro ...”:命令a期望\跟随通过文本”。如果我遗漏了一些重要的东西,我很抱歉。
  • ^^ 这其实是对的。即使是启发式的,当脚本第二次运行时,这些条目也将在最后。但看起来你的答案已经涵盖了。
猜你喜欢
  • 2019-12-31
  • 1970-01-01
  • 1970-01-01
  • 2022-07-12
  • 2019-09-02
  • 2021-03-13
  • 2017-07-10
  • 1970-01-01
  • 2016-11-29
相关资源
最近更新 更多