将变量与包含空格 (\s) 和 sed 的正则表达式一起使用

Using Variables with Regex that contain a space (\s) and sed

提问人:john Wallace 提问时间:1/2/2020 更新时间:1/2/2020 访问量:392

问:

我尝试使用文字字符串变量和正则表达式创建排序脚本,并在 bash 中使用 sed 创建排序脚本。使用变量时,我似乎找不到带有空格的文字字符串,尽管在直接使用正则表达式时可以找到它们。所以:

#!/bin/bash
group1="IRISHFHD"
group2="REGIONAL FHD"

sed -i '/group-title="'${group1}/',+1d' JWLINE.m3u
sed -i '/group-title="'${group2}/',+1d' JWLINE.m3u

我尝试将 \s 添加到组变量中,但它不起作用。

John

正则表达式 bash 变量 sed

评论

0赞 shellter 1/2/2020
您真的希望在匹配字符串中使用单个 dbl 引号(不匹配的对)吗?祝你好运。
0赞 Wiktor Stribiżew 1/2/2020
你要找 ?sed -i '/group-title="'"$group2"'/,+1d' JWLINE.m3u
0赞 john Wallace 1/2/2020
为什么我的所作所为很奇怪?正则表达式对我来说是新的。
0赞 Brenda J. Butler 1/2/2020
扩展 @shellter 的评论:您匹配的是 /group-title=“IRISHFHD。也许你应该匹配 /group-title=“IRISHFHD”(注意右双引号)?你可以写 sed -i '/group-title=“'”${group1}“'/,+1d' JWLINE.m3u .m3u(我还在 shell 变量 ${group1} 周围添加了双引号,正如 Gordon Davisson 的回答中所建议的那样 - 需要保护其中一个 shell 变量值中的空间 - 正如 Gordon 解释的那样)。不过,这似乎是一种艰难的排序方法。如果你可以安排把每个元素放在一行上,那么你可以用 sort(1) 工具对行进行排序。

答:

2赞 Gordon Davisson 1/2/2020 #1

这个问题与正则表达式无关,这完全取决于 shell 如何处理变量的值。当一个变量被扩展而没有双引号时(即 ),shell 会根据空格将其拆分为“单词”。它还将尝试将任何包含 shell 通配符的单词扩展为匹配文件的列表,并且一些正则表达式元字符看起来像 shell 通配符,这可能会导致严重的混乱。${group2}

在此示例中:

sed -i '/group-title="'${group2}/',+1d' JWLINE.m3u

这有点复杂,因为变量引用位于两个单引号部分之间。在这种情况下,变量引用之前的部分附加到变量中的第一个“单词”,之后的部分附加到最后一个单词。从本质上讲,它扩展为以下等价物:

sed -i '/group-title="REGIONAL' 'FHD/,+1d' JWLINE.m3u
                               ^ That's a space between arguments

无论如何,由于它在空格上被拆分,因此得到两个部分参数而不是一个完整的参数,并且它根本不起作用。sed

解决方案:与几乎所有情况一样,您应该在变量引用周围使用双引号,以防止出现这样的奇怪效果。有几个选项。你可以在变量部分周围添加双引号:

sed -i '/group-title="'"${group2}"/',+1d' JWLINE.m3u

...但 IMO 这令人困惑;其中一些引号是语法的(即由 shell 解析),一个是字面的(作为正则表达式的一部分传递给),哪些是哪个并不明显。我宁愿在整个事情周围使用双引号,并转义应该是字面意思的双引号:sed

sed -i "/group-title=\"${group2}/,+1d" JWLINE.m3u
                     ^^ Escape makes this " a literal part of the argument.

(在双引号中,您还需要转义任何美元符号、反斜杠或反引号,这些符号本应是参数的字面部分。但在这种情况下,没有这些。

评论

1赞 Gordon Davisson 1/2/2020
的内容是什么?另外,你用的是哪个?不同的版本(例如GNU与bsd)的行为略有不同(例如,GNU版本可以识别为,但bsd版本不会;bshd需要文件扩展名参数(或没有备份),但GNU不需要;等等)。另外,试着把这个麻烦的命令放在前面(在它后面加上'set +x),shell会打印出相当于扩展后的命令,这可能会澄清发生了什么。JWLINE.m3used\s[[:space:]]-i''set -x
0赞 john Wallace 1/2/2020
对不起,戈登,我的错。事实上,您的建议非常有效。感谢您的帮助。
1赞 Paul Hodges 1/2/2020
顺便说一句,这不能在一次执行中完成吗?sed -i "/group-title=\"${group1}/,+1d; /group-title=\"${group2}/,+1d" JWLINE.m3u