假设我有一个文件,其中包含多次出现的 StringA 和 StringB。我想用 StringB 替换所有出现的 StringA,并且(同时)用 StringA 替换所有出现的 StringB。
现在,我正在做类似的事情
cat file.txt | sed 's/StringB/StringC/g' | sed 's/StringA/StringB/g' | sed 's/StringC/StringA/g'
Run Code Online (Sandbox Code Playgroud)
这种方法的问题在于它假定文件中没有出现 StringC。虽然这在实践中不是问题,但这个解决方案仍然让人感觉很脏——也就是说,它感觉像是一个学习更多 Unix 魔法的机会。:)
Gil*_*il' 15
如果StringB
和StringA
不能出现在同一输入行上,那么您可以告诉 sed 以一种方式执行替换,并且只有在没有出现第一个搜索字符串时才尝试另一种方式。
<file.txt sed -e 's/StringA/StringB/g' -e t -e 's/StringB/StringA/g'
Run Code Online (Sandbox Code Playgroud)
在一般情况下,我认为 sed 中没有简单的方法。顺便说一句,请注意,如果StringA
并且StringB
可以重叠,则规范是不明确的。这是一个 Perl 解决方案,它替换任一字符串的最左边出现并重复。
<file.txt perl -pe 'BEGIN {%r = ("StringA" => "StringB", "StringB" => "StringA")}
s/(StringA|StringB)/$r{$1}/ge'
Run Code Online (Sandbox Code Playgroud)
如果您想坚持使用 POSIX 工具,那么 awk 是您要走的路。awk 没有用于一般参数化替换的原语,因此您需要自己动手。
<file.txt awk '{
while (match($0, /StringA|StringB/)) {
printf "%s", substr($0, 1, RSTART-1);
$0 = substr($0, RSTART);
printf "%s", /^StringA/ ? "StringB" : "StringA";
$0 = substr($0, 1+RLENGTH)
}
print
}'
Run Code Online (Sandbox Code Playgroud)
现在,我正在做类似的事情
…………
这种方法的问题在于它假设文件中没有出现 StringC。
我认为你的方法很好,你应该只使用其他东西而不是字符串,不能在一行中出现的东西(在模式空间中)。最佳人选是\n
ewline。
通常,模式空间中的任何输入行都不会包含该字符,因此,要交换文件中所有出现的THIS
和THAT
,您可以运行:
sed 's/THIS/\
/g
s/THAT/THIS/g
s/\n/THAT/g' infile
Run Code Online (Sandbox Code Playgroud)
或者,如果您的 sed 也支持\n
RHS:
sed 's/THIS/\n/g;s/THAT/THIS/g;s/\n/THAT/g' infile
Run Code Online (Sandbox Code Playgroud)