更好的做“ echo $ x | sed…”和“ echo $ x | grep……”


14

我经常在脚本中找到它(而且我必须承认,请自己编写):

a=$(echo "$x" | sed "s/foo/bar/")

要么

if echo "$x" | grep -q foo
then
    ...
fi

考虑“ foo”包括一些正则表达式的东西。

我认为应该-很有可能 -一种更好的措辞,一种不涉及两个命令和管道但将其包装成更紧凑的表达式的方式。

我只是找不到。有人吗


我希望由于无知(不知道替代方案)和可维护性(知道替代方案但将其选择为更易于理解)的组合而经常使用该表达式。我可以一目了然地告诉您您的示例的功能,但是我需要一个shell参考来找出grawity和Dan McG的答案中的替代方法。
quack quixote

3
顺便说一句,执行命令替换的首选方法是使用$()而不是反引号。
暂停,直到另行通知。

2
引用扩展名也是一个好主意,以便保护空白:a="$(echo "$x" | sed "s/foo/bar/")"if echo "$x" | grep foo; …
克里斯·约翰森

在$()与``上有很好的注释。我发现我的bash技能还不是很好。
DevSolar

Answers:


12

除非您假设使用特定的外壳,否则没有比“将管道回传到工具”(或像expr那样的“工具”本身)更好的方法了;传统的Bourne外壳和/或POSIX外壳是您真正可以依靠的。如果考虑其他外壳,那么还有其他一些内置的可能性。

ksh

  • 额外的模式:?(pattern-list)*(pattern-list){n}(pattern-list){n,m}(pattern-list)@(pattern-list)!(pattern-list)
  • 所述%P 的printf说明符的扩展正则表达式转换成的图案(和%R用于扩展正则表达式到图案);
  • expr == pattern在条件[[ expr ]]测试;
  • ${param/pattern/replacement}参数扩展。

重击

  • extglob使大部分的额外模式的选项KSH(不{n}{n,m});
  • expr == pattern条件(在[[ expr ]]测试);
  • ${param/pattern/replacement}参数扩展;
  • (在新版本中)可以与扩展正则表达式匹配的expr =~ extregexp条件(在[[ expr ]]测试中)
    • 使用带括号的子表达式和BASH_REMATCH参数,可以完成sed -style替换。

zsh

  • 带有EXTENDED_GLOB选项的自己的扩展模式;
  • 带有ksh的扩展模式(带有KSH_GLOB选项);
  • expr == pattern条件(在[[ expr ]]测试);
  • ${pattern/pattern/replacement}参数扩展;
  • expr =~ extregexp(在[[ expr ]]测试中)可以与扩展正则表达式匹配的条件,
    • 如果设置了RE_MATCH_PCRE选项,则可以使用PCRE代替普通的扩展正则表达式,
    • 使用带括号的子表达式,MATCH参数和match参数(或BASH_REMATCH使用BASH_REMATCH选项集),可以完成sed样式的替换;
  • zsh/pcre模块提供pcre_compilepcre_study以及pcre_match命令和-pcre-match 测试条件(在[[ expr ]]测试);
  • zsh/regex提供-regex-match 测试条件的模块(在[[ expr ]]测试中)。

哇。如人们所希望的那样完整。绝对是赢家。
DevSolar

6

要替换sed行,请执行以下操作

${a/foo/bar} 要么 ${a//foo/bar}

在第一种形式中,仅第一个实例被替换。第二种形式是全局搜索和替换。

在您的情况下,

代替:

if echo $x | grep foo
then
    ...
fi

考虑使用:

if [ $x =~ foo ]
then
    ...
fi

foo正则表达式在哪里。


在哪些外壳中起作用?
珀尔帖

1
if [ $x =~ foo ]在此处给出错误消息。if [[ $x =~ foo ]]但是,效果很好。谢谢!
DevSolar 2010年

1
所有这些都是bashisms,它们需要bash。另外,=~要求bash> = 3 iirc。
ℝaphink

1
同样,irir,在这些示例中,foo不是正则表达式(如在PCRE中),而是使用通配符。在bash手册页的“参数扩展”部分中,还有更多bash优点。我特别喜欢${a##foo}和这样的事情${a%%bar}
ℝaphink

3
match运算符=~确实使用正则表达式。例如,这是正确的:(例如[[ "abcdddde" =~ ^a.*d+.g* ]],等于或大于零的g而不是g通配符)。
暂停,直到另行通知。

2

与posix兼容的一种很好的测试变量是否包含模式的方法是:

test ${var##*foo*} || <do something>;

参数扩展的语法为:

 ${parameter##pattern}

其中pattern是一个壳图案

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.