gpt4 book ai didi

linux - 正则表达式在通过 ssh 的 sed 中不被接受

转载 作者:太空宇宙 更新时间:2023-11-04 09:16:53 25 4
gpt4 key购买 nike

我正在尝试通过 ssh 在 bash 脚本中编辑远程文件:

文件看起来像这样:

{
"lastqueueid" : "7865904306",
"jobqueuetimestamp" : "1506489874000",
"mincleanstartsegment" : "7516101",
"lastposition" : "519949359362951172",
"maxsegment" : "7566259"
}

我正在尝试使用 sed 将 "lastqueueid"7865904306 更改为 $LATEST_QUEUE。所以我尝试...

ssh user@host sed \
"s@"lastqueueid"\s\:\s\"[0-9]+\"@"lastqueueid"\s\:\s"$LATEST_QUEUE"@g" \
/file.json

sed 不会抛出错误,但它也不会进行替换。似乎它没有将 \s 视为空白。如果我删除 \s 并改为添加文字空格,我会得到可怕的 unterminated `s' command 错误。

如有任何帮助,我们将不胜感激。谢谢!

最佳答案

这里至少存在三个问题:

  1. 许多版本的 sed 不理解 \s -- 这是 perl 的东西。您将在 unix/linux 系统上遇到正则表达式语法的三种主要变体: basic (BRE), extended (ERE), and perl-compatible (PCRE)sed 默认使用 BRE,但可以通过 -r-E 选项告诉它使用 ERE 语法(取决于 的版本code>sed 你有)。 BRE 和 ERE 语法中 \s 的等价物是 [[:space:]]

    另一个问题是 BRE 语法无法识别 +(如 [0-9]+)。只需使用 [0-9][0-9]*。哦,您不需要在任何 RE 语法中转义 :

  2. 引号不嵌套。当您使用 "s@"lastqueueid"\s... 时,shell 将 "s@" 视为带引号的字符串,将 lastqueueid 视为一个不带引号的字符串, "\s... 作为另一个带引号的字符串的开头,等等。您需要将内部引号视为字符串的一部分,而不是围绕它(的一部分)的定界符(也就是说,您需要文字而不是句法引号)。一种方法是转义应为文字的引号 ("s@\"lastqueueid\"\s...),另一种方法是使用不同类型的引号(单引号与双引号) 用于外部引号('s@"lastqueueid"\s...' -- 但 $variable 不会在单引号中展开)。

    但是还有另一个复杂的问题,因为...

  3. 由于此命令是通过 ssh 传递的,因此它经历了 shell 解析和引号/转义解释和删除的整个过程两次,一次在本地计算机,然后再次通过远程计算机上的 shell。这意味着您需要在引号周围加上引号(第一个由本地 shell 解释和删除,第二个由远程 shell 解释和删除,第三个被视为要匹配的模式的一部分)。这变得困惑。

    顺便说一句,这第三个问题是为什么当您使用实际空格时会收到“未终止的‘s’命令”错误——当它到达远程 shell 时,命令如下所示:

    sed s@lastqueueid : '[0-9]+@lastqueueid' : 123456789@g /file.json

    ... 所以 sed 尝试将 s@lastqueueid 作为命令执行(其余所有都是文件名),但无法解析它。

那么,怎么办?在我看来,最简单的引用策略是在转义双引号周围使用双引号围绕单引号。像这样:

"'s@\"lastqueueid\" : \"[0-9][0-9]*\"@\"lastqueueid\" : \"$LATEST_QUEUE\"@g'"

在被本地 shell 解析后,ssh 接收(并传递给远程 shell)如下内容:

's@"lastqueueid" : "[0-9][0-9]*"@"lastqueueid" : "123456789"@g'

...远程 shell 删除单引号,sed 得到这个:

s@"lastqueueid" : "[0-9][0-9]*"@"lastqueueid" : "123456789"@g

...这就是您想要的。

嗯,也许吧。我看到了其他几个可能的问题。首先,该文件实际上是/file.json(即位于远程文件系统的根目录中)吗?如果不是,请修复路径。其次,您是否试图用编辑后的版本替换远程文件?默认情况下,sed 只打印出编辑后的版本,并不保存。要进行就地编辑,请使用 -i.bak(其中“.bak”是用于保存预编辑备份的文件扩展名)。

关于linux - 正则表达式在通过 ssh 的 sed 中不被接受,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46459714/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com