使用 sed:如何保护替换的标点符号

使用 sed:如何保护替换的标点符号

在与计算机交互方面,我是一个完全的新手,但我正在开发一个项目,如果不制作脚本我就无法跟上,所以我需要帮助。

我的文件中的一行中有两个字符串,我想使用 sed 替换它们。问题是它们非常相似,我不知道如何独立替换它们。

我要替换的行是这样的:

*xyzfile 0 1 somefilebeingpointedto.xyz

我想以这一行结束:

*xyz 0 1

由于 0 和 1 在文件之间发生变化,并且最后一个字符串中的“.xyz”之前没有保守字符串,所以我不知道如何执行此操作或简单地替换整行。

我一直在尝试使用以下两行 sed:

sed -i 's/^.*xyzfile/\*xyz/' myfile.inp
sed -i 's/^.\.xyz/" "/' myfile.inp

顺序没有什么区别,似乎 sed 根本没有将句点视为第二行中字符串的一部分。

如果有更好的方法来实现这一点,我洗耳恭听!谢谢

答案1

您的第二个示例的问题是它根本与您的线路不匹配。它试图匹配^.\.xyz,即:<beginning of line><any character>.xyz。但我怀疑你正在尝试匹配<some characters>.xyz<end of line>。到目前为止,您需要删除^,然后您需要弄清楚如何根据<some characters>您的情况进行定义。

但是你不需要两次 sed 调用,因为你可以保持模式在 sed 中。如果你包围了你想要的图案保持使用(转义的)括号,您可以稍后将它们替换为\1(或\2第二个模式,依此类推)。

所以你想去掉file最后的文件名:

*xyzfile 0 1 somefilebeingpointedto.xyz

所以模式我思考您正在寻找的是(其中包含文字“文件”):

<something to keep>file<something to keep><space><pattern without spaces until end of line>

我们可以将其与:

^\(.*\)file\(.*\) [^ ]*$

请注意,我们要保留的两个部分放在(转义的)括号内。如果我们不想保留它们供以后使用,我们可以去掉括号 ( .*file.* [^ ]*)

接下来,通过 sed 的替换,您将得到如下所示的完整行:

sed 's/^\(.*\)file\(.*\) [^ ]*$/\1\2/'

答案2

sed 正则表达式中的点表示任意角色, 但只有字符。
因此,正则表达式^.\.xyz的意思是:从行首开始,匹配字符,然后一个点,然后xyz.你的意思可能是:^.*\.xyz$,但这会匹配所有的线(并删除它)。您应该使用空格作为分隔符(假设文件名中没有空格):[^ ]*\.xyz$,这意味着:从空格 ( " ") 开始匹配几个 ( *) 非空格 ( ) 字符,直到行末尾的[^ ]扩展名.xyz( $)。如果在每个部分前面加上-e:则可以表达这两个替换:

sed -e 's/^.*xyzfile/*xyz/' -e 's/ [^ ]*\.xyz$//' myfile.inp

无需转义*替换右侧的 。

这可以简化为:

sed -e 's/xyzfile /*xyz /' -e 's/ [^ ]*\.xyz$//' myfile.inp

文件名中的空格

如果文件名可能包含空格,则正则表达式会变得更加复杂,因为没有简单的方法来选择(仅)该行的该部分。

如果第二个和第三个字段只有一个字符,您可以使用捕获括号并将其放回\1

sed -e 's/xyzfile\( . .\) .*\.xyz$/xyz\1/' myfile.inp

扩展正则表达式语法:

sed -E -e 's/xyzfile( . .) .*\.xyz$/xyz\1/' myfile.inp

或者,如果字段可以有多个字符(空格除外):

sed -E -e 's/xyzfile( [^ ]* [^ ]*) .*\.xyz$/xyz\1/' myfile.inp

如果该行类似于 (no xyzfile),则可能会失败:

*xyzffff 0 1 pointedto.xyz

在这种情况下,独立应用每个替换:

sed -E -e 's/xyzfile /xyz /' -e 's/( [^ ]* [^ ]*) .*\.xyz$/\1/' myfile.inp

相关内容