如何使用grep的-E选项匹配某些变量名

如何使用grep的-E选项匹配某些变量名

我们想知道通过使用 grep -E 选项来匹配某些变量名称(包括其 $ 前缀)的正确方法。
看来这个 grep macthing 函数只能在没有任何选项或 -e 选项的情况下工作......

> 
> 
> grep ""'$'status"" /home/ewpadm/.sapenv_wzwms1.csh
if ( $status == 0 ) then
if ( $status == 0 ) then 
    set rc1 = $status
    set rc2 = $status
    set rc3 = $status
    set rc4 = $status
    set rc5 = $status
    set rc6 = $status
    set rc7 = $status
    set rc8 = $status
> 
> 
> grep -E ""'$'status"" /home/ewpadm/.sapenv_wzwms1.csh
> 
> 
> grep -E """'$'status"""" /home/ewpadm/.sapenv_wzwms1.csh
> 
> 
> grep -e ""'$'status"" /home/ewpadm/.sapenv_wzwms1.csh 
if ( $status == 0 ) then
if ( $status == 0 ) then 
    set rc1 = $status
    set rc2 = $status
    set rc3 = $status
    set rc4 = $status
    set rc5 = $status
    set rc6 = $status
    set rc7 = $status
    set rc8 = $status
> 
> 
> grep -e "= "'$'status"" /home/ewpadm/.sapenv_wzwms1.csh
    set rc1 = $status
    set rc2 = $status
    set rc3 = $status
    set rc4 = $status
    set rc5 = $status
    set rc6 = $status
    set rc7 = $status
    set rc8 = $status
> 
>  

答案1

$是 shell 的特殊字符(用于引入一些扩展,例如$param, $(cmdsubst),$((arithmetic)))和正则表达式(在所有基本的,扩展( -E,以前egrep),珀尔( -P//-X perl--perl-regexp ),增强的( -X/ --augmented-regexp)) 表示在主语末尾匹配,因此您需要对两者进行转义,最好在'...'for shell 和正则表达式中使用\$or进行转义(并且在大多数 shell 中也很特殊,也可以用 引起来) :[$]\[...]'...'

在基本 RE(没有-E/ -P/ -X...)中,$仅在正则表达式末尾或在某些情况下 a 之前是特殊的,因此\)这里正则表达式可以是$status,而在其他正则表达式变体(包括扩展正则表达式)中,它通常总是特殊的,因此正则表达式必须是\$status[$]status

使用(以前的)-F选项grepfgrep固定字符串避免必须进行正则表达式转义。类似 Perl 的正则表达式也可以\Q...\E用于引用。所以,有很多选择:

grep -F '$status'
grep    '$status'
grep    '\$status'
grep    '[$]status'
grep -E '\$status'
grep -E '[$]status'

非标:

grep -P '\$status'
grep -P '[$]status'
grep -P '\Q$status\E'
grep -X '\$status'
grep -X '[$]status'

在某些 shell 中,\and"也可以用作引用运算符,但反斜杠 和$在 中通常仍然是特殊的"...",因此这会使其在这里变得尴尬。'...'是最强的引号(在某些 shell 中,如rc 和 派生物,是唯一的引号),因此您通常希望在 regexp 周围使用这些引号,其中许多运算符 ( ^$*?\[](){}|) 在大多数 shell 的语法中也恰好是特殊的。

无论如何,那些也会$status在里面找到

  • $status2$status_old或者$statusing
  • $$status$$其次是status
  • \$status$status或任何引用字面意思的csh

并且不会发现

  • ${status}
  • ${status[1]}(下标)
  • ${status:q}(修饰语)
  • $#status${#status}(字数)
  • $%status${%status}(字符数)
  • @ status++/ if ( status == 0 ) then(数学表达式,其中变量(有时)可以在没有$前缀的情况下使用)。

使用字边界运算符(\b在 perl 或增强正则表达式中\b\>[[:>:]]在 BRE 或 ERE 的某些实现中作为非标准扩展)将有助于解决第一类问题:

grep -P '\$status\b'

没有字边界,可以手动完成:

grep -E '\$status([^_[:alnum:]]|$)'
grep    '$status\([^_[:alnum:]].*\)\{0,1\}$'

我们寻找的是$status后面跟着一个不属于变量名的字符或行尾,或者在没有交替运算符¹的 BRE 中,但如今具有\{0,1\}与 ERE 等价的字符?$status后面跟着一个非变量成分和任意数量的字符,直到行尾。

解决更多问题:

grep -P '\$\{?[#%]?status\b'
grep -E '\$\{?[#%]?status([^_[:alnum:]]|$)'
grep    '${\{0,1\}[#%]\{0,1\}status\([^_[:alnum:]].*\)\{0,1\}$'

1 尽管某些grep实现将\|其作为非标准扩展。

相关内容