我正在尝试使用SED从日志文件中提取文本。我可以轻松进行搜索和替换:
sed 's/foo/bar/' mylog.txt
但是,我想使搜索不区分大小写。从我搜索过的内容来看,似乎i
可以在命令末尾附加内容:
sed 's/foo/bar/i' mylog.txt
但是,这给了我一条错误消息:
sed: 1: "s/foo/bar/i": bad flag in substitute command: 'i'
这里出了什么问题,我该如何解决?
我正在尝试使用SED从日志文件中提取文本。我可以轻松进行搜索和替换:
sed 's/foo/bar/' mylog.txt
但是,我想使搜索不区分大小写。从我搜索过的内容来看,似乎i
可以在命令末尾附加内容:
sed 's/foo/bar/i' mylog.txt
但是,这给了我一条错误消息:
sed: 1: "s/foo/bar/i": bad flag in substitute command: 'i'
这里出了什么问题,我该如何解决?
man sed
与实现保持一致-不提及(并且在实践中不提供支持)不区分大小写的匹配;如果您发现有其他要求的文档,请告知我们。
Answers:
需要明确的是:在macOS上-自Mojave(10.14)起--sed
这是BSD实现-不支持不区分大小写的匹配-难以置信,但事实如此。在以前接受的答案,这本身就说明一个GNU sed
命令,获得因为这种地位perl
在评论中提到基于解决方案。
要使该Perl解决方案也可以通过UTF-8与外来字符一起使用,请使用以下方法:
perl -C -Mutf8 -pe 's/öœ/oo/i' <<< "FÖŒ" # -> "Foo"
-C
假设当前语言环境基于UTF-8,则打开对流和文件的UTF-8支持。-Mutf8
告诉Perl将源代码解释为UTF-8(在这种情况下,将字符串传递给-pe
)-这是更冗长的等价形式的较短等效词,-e 'use utf8;'.
谢谢,Mark Reed(请注意,使用awk
也不是一个选项,例如awk
在macOS上(即BWK awk,又名BSD awk)似乎完全不知道语言环境-它tolower()
和toupper()
函数会忽略外来字符(并且sub()
/gsub()
对大小写不区分大小写)首先)。)
编者注:该解决方案不适用于macOS(开箱即用),因为它仅适用于GNU sed
,而macOS随附BSD sed
。
大写“ I”。
sed 's/foo/bar/I' file
/gI
othewise它只是在第一场比赛操作。
sed
在Mac OS X上,另一个解决方法是gsed
从MacPorts或HomeBrew安装,然后创建别名sed='gsed'
。
brew install gnu-sed
然后使用我的〜/ .bash_profile并添加别名。感谢@davmat
brew install gnu-sed --with-default-names
-这将覆盖默认值sed
。
如果您要先进行模式匹配,例如
/pattern/s/xx/yy/g
那么您想I
在模式之后放置:
/pattern/Is/xx/yy/g
例:
echo Fred | sed '/fred/Is//willma/g'
回报willma
; 如果不使用I
,则返回未修改的字符串(Fred
)。
sed: 1: "/fred/Is//willma/g": invalid command code I
sed -r '/'"$PATTERN"'/I,${s//'$YELLOW'&'$NO_COLOR'/g;b};$q3'
。它会打印文本,如果找到了模式(不区分大小写),则会以黄色(ansi颜色)突出显示文本。如果没有找到-返回退出代码3
我也有类似的需求,并提出了以下建议:
此命令仅查找所有文件:
grep -i -l -r foo ./*
排除this_shell.sh(如果您将命令放在名为this_shell.sh的脚本中),将输出发到控制台以查看发生了什么,然后在找到的每个文件名上使用sed,用bar替换文本foo :
grep -i -l -r --exclude "this_shell.sh" foo ./* | tee /dev/fd/2 | while read -r x; do sed -b -i 's/foo/bar/gi' "$x"; done
我选择了这种方法,因为我不希望为未修改的文件更改所有时间戳。提供grep结果仅允许查看带有目标文本的文件(因此也可能会提高性能/速度)
使用前请务必备份文件并进行测试。在某些环境中,对于带有嵌入式空间的文件可能不起作用。(?)
使用以下命令替换所有出现的内容:sed's / foo / bar / gI'mylog.txt
I
。我也认为这并不能真正解决问题,因为它没有询问有关全局替换的问题。
I
是GNU扩展,可能与您的sed副本不可用。