sed 中的非贪婪匹配

sed 中的非贪婪匹配

在 bash 脚本中,我有以下变量:

file_name='this_is_the_hart_part.csv'

使用

var2=$(echo $file_name | sed -e 's/_{2}\(.*\)_{3}/\1/')

我想提取子字符串“the”(变量 $file_name 中的下划线数字 2 和 3 之间)。

但是我得到的 $var2 等于 $file_name。我该如何更改我的 sed 命令?

答案1

支持的正则表达式类型sed不允许与 进行非贪婪匹配*

您想要获得第三个_分隔字段。这是最简单的方法cut

cut -d '_' -f 3

或者,与awk

awk -F '_' '{ print $3 }'

或者,在 shell 中,连续删除前两个此类字段,然后修剪末尾:

str=${file_name#*_}
str=${str#*_}
str=${str%%_*}

"$str"就是the最后这个词。使用最后一个变体可能是这三种方法中最快、最可靠的方法。

变量替换${variable#*_}将产生一个字符串,该字符串的$variable前导位直到并包括第一个下划线被删除。将${variable%%_*}删除从第一个下划线到结尾的所有内容$variable。这些是标准变量替换。

在文件名上使用变量替换的好处是它可以处理包含换行符的文件名,而 或awksedcut不会。一般来说,不要对文件名使用面向行的文本编辑工具。

此外,您正在使用echo $file_name.由于$file_name未加引号,因此它将经历单词分割(默认情况下,在也是空格、制表符和换行符的每个字符上$IFS),并且生成的单词(如果它们包含文件名通配字符)将与当前目录中的文件名进行匹配通过外壳。文件名中的反斜杠也可能会消失或产生不需要的效果(即使您引用扩展名)。当未加引号时,shellksh还会对 的值进行大括号扩展。$file_name

答案2

首先要注意的sed文本默认情况下一次只处理一行的实用程序,而文件名可以包含任何字符(包括换行符)甚至非字符(可以是非字符)文本)。

还,不加引号的变量有非常特殊的含义,你几乎不想这样做,这也是潜在非常危险

还,你不能用来echo输出任意数据,printf而是使用

另外,类似 Bourne 的 shell 中的变量赋值语法是:var=value,而不是$var=value

echo您可以使用以下命令将(或更好的是printf)的整个输出加载到sed的模式空间中:

printf '%s\n' "$filename" | sed -e :1 -e '$!{N;b1' -e '}'

然后,您可以添加代码来提取第二个和第三个之间的部分_

var2=$(
  printf '%s\n' "$filename" |
   sed -ne :1 -e '$!{N;b1' -e '}' -e 's/^\([^_]*_\)\{2\}\([^_]*\)_.*/\2/p'
)

非贪婪部分是通过使用[^_]*(一系列非_字符)来解决的,这与.*保证我们不匹配过去的_边界相反(尽管在许多实现中它仍然会被非字符阻塞)。

在这种情况下,您可以改用 shell 参数扩展运算符:

case $filename in
  (*_*_*_*) var2=${filename#*_*_}; var2=${var2%%_*};;
  (*)       var2=;;
esac

如果文件名不是文本或者您想要提取的部分以换行符结尾(并且也会更有效),则效果会更好。

有些 shell 喜欢zshksh93有更高级的运算符:

  • zsh:

    拆分_并获取第三个字段:

    var2=${"${(@s:_:)filename}"[3]}
    

    使用${var/pattern/replacement}和 反向引用(在这种情况下,您需要首先验证变量是否包含至少 3 个下划线,否则不会有任何替换)。

    set -o extendedglob
    var2=${filename/(#b)*_*_(*)_*/$match[1]}
    
  • ksh93:

    var2=${filename/*_*_@(*)_*/\1}
    

答案3

@Kusalananda 是对的,这sed是错误的工具,你不能进行非贪婪匹配。但是您可以使用非贪婪匹配的解决方法: [^_]*将匹配任何不是的字符_

所以在你的情况下你可以这样做:

printf '%s\n' "$file_name" | sed -e 's/^[^_]*_[^_]*_\([^_]*\).*$/\1/g'

但是...对于您的用例,您应该更好地使用其他工具...

相关内容