sed - 匹配行首非特定字符

4
我正在尝试编写一个命令,用于替换行首以外的文本:
echo -e 'a b b\nb b c' | sed 's%^b%x%g'

输出:

a b b
x b c

期望的输出:

a x x
b x c

我正在编写一个脚本,用于解析一个400MB的文件,这个问题困扰我已经有一段时间了。
5个回答

3
这应该适用于多个字符的组合:
sed 's/^b/\
/; s/b/x/g; s/^\n/b/' 

有些sed命令在替换部分接受\n,所以在这种情况下:

sed 's/^b/\n/; s/b/x/g; s/^\n/b/'

应该也能工作


模式空间中使用换行符的方式很巧妙。 :-) - torek
谢谢 :) 很高兴你注意到了这个换行符的使用 ;) - Scrutinizer

2
这应该可以解决问题:
echo -e 'a b b\nb b c' | sed 's%\(.\)b%\1x%g'

如果有多个连续的 b,将不会替换所有出现。 - Andrew Clark
抱歉,我没有意识到那是一个要求。 - Sean Bright
可能不是,我不是原帖作者 :) - Andrew Clark

1
借鉴Scrutinizer's idea,这里有一种更通用的保护行部分的方法。技巧在于我们将(单行)模式空间并插入“要保护的部分”后面的换行符。然后,我们仅对“换行符后面的内容”进行更改。最后,我们删除保护性换行符。
此版本更改了除任何(一个或多个)“行首”b之外的所有b,因此例如“b b c”变为“b x c”,但是“bbc bbc”变为“bbc bxc”而不是“bxc bxc”。
sed -e 's/^b*/&\
/
s/\n\(.*\)b/\1x/g
s/\n//'

相同的方法也可以用于保护一行末尾的文本,不过这要困难得多。

注意:这种方法不够高效,因为sed现在必须对每一行进行两次更改,一次是添加保护器,另一次是移除它。如果你只想保护多个前导的b,你可以将它们全部转换成换行符,然后再转换回来。这更适用于保护每一行的第一个“单词”。


0
你的系统上是否有Perl可用?如果是这样,这将作为sed命令的直接替代品。
perl -pe '($c,$_)=/(.)(.*)/s;s/b/x/g;$_=$c.$_'

0
这可能适用于您(GNU sed):
sed '/^b/s/b/x/2g;/^b/!s/b/x/g' file

或者

sed -r ':a;s/^(..*)b/\1x/;ta' file

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接