在与计算机交互方面,我是一个完全的新手,但我正在开发一个项目,如果不制作脚本我就无法跟上,所以我需要帮助。
我的文件中的一行中有两个字符串,我想使用 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