BASH:如何在 sed 命令中对字符串使用 Regex Negative Lookahead?

Ros*_*ose 2 regex bash sed

我还没有找到在 sed 命令中使用此正则表达式 - .+?(?=,) 来提取该字符串的一部分的方法(使用第一个字符实例的 Lookbehind)。

用简单的英语来说,我想提取第一个逗号之前的字符串部分。由于我计划将来提取字符串的特定文件名,因此我不能依赖 cut 命令(我最终必须使用 sed 命令),:-

name='错误 1:/home/rphillips/Desktop/empties/BN23_2303.tif,带 1:无法计算统计信息,采样中未找到有效像素。'

这些是我使用过的变体,包括有效的测试 - sed 's/band/rose/'。然而,我使用的其他变体(如下所示)给出了空格作为输出。

while read -r line; do
    name="$line"
    echo $name
    #file_path=$(echo $name | cut -d "," -f 1)
    #file_path=$(echo $name | sed -e '/s\/.+?(?=,)///')
    #file_path=$(echo $name | sed 's/band/rose/')
    file_path=$(echo $name | sed '/s\/.+?(?=, )///')
    #file_path=$(echo $name | grep -P '.+?(?=,)')
    #file_path=$(echo $name | sed 
    #file_path=$(echo $name | awk '/.+?(?=,)/{print $name}'
    echo $file_path
done < "$filename"
Run Code Online (Sandbox Code Playgroud)

预期结果 - 错误 1:/home/rphillips/Desktop/empties/BN25_2303.tif

实际结果 - “很多空间

我还注意到,根据 Regex101 网站,我使用的正则表达式具有不同的“匹配”,具体取决于我在 Windows 上使用 Firefox 还是 Ubuntu 16.04LTS

Windows - https://regex101.com/r/WWGf8F/1 Ubuntu - https://regex101.com/r/NpL2Oa/1

我不确定这是否会导致表达式无法被识别sed -e

我已将这些引用用于上面代码中使用的不同表达式

https://likegeeks.com/regex-tutorial-linux/

如何在正则表达式中匹配“直到这个字符序列的任何内容”?

https://www.regular-expressions.info/lookaround.html?wlr=1

https://linux.die.net/man/1/sed

Dav*_*ica 5

用简单的英语来说,我想提取字符串中第一个逗号之前的部分。由于我计划将来提取字符串的特定文件名,因此我不能依赖 cut 命令(我最终必须使用sed命令)

输入字符串

ERROR 1: /home/rphillips/Desktop/empties/BN23_2303.tif, band 1: Failed to compute statistics, no valid pixels found in sampling.
Run Code Online (Sandbox Code Playgroud)

预期成绩

ERROR 1: /home/rphillips/Desktop/empties/BN25_2303.tif
Run Code Online (Sandbox Code Playgroud)

在我们了解sed命令不起作用的可能原因之前,让我们先看看上面的实际问题。如果您只想提取第一个逗号之前的文本,那么您需要的是:

sed 's/,.*//'
Run Code Online (Sandbox Code Playgroud)

(这只是说删除从第一个逗号到结尾的所有内容)

您也可以使用反向引用(这将有助于实现提取文件名的最终目标),例如

sed 's/^\([^,][^,]*\).*$/\1/'
Run Code Online (Sandbox Code Playgroud)

(这表示'^'从头开始,\([^,][^,]*\)捕获至少 1 个非逗号字符的所有文本,并包括零个或多个非逗号的其他字符,.*$丢弃所有文本到末尾,\1使用后退仅替换捕获的文本-参考)

要达到仅提取文件名的目标,您只需修改上面的内容即可以第一个正斜杠开始捕获,例如

sed 's/^[^/]*\([^,][^,]*\).*$/\1/'
Run Code Online (Sandbox Code Playgroud)

使用/输出示例

$ sed 's/^[^/]*\([^,][^,]*\).*$/\1/' <<< $name
/home/rphillips/Desktop/empties/BN23_2303.tif
Run Code Online (Sandbox Code Playgroud)

我不确定这是否会导致表达式无法被识别 sed -e

sed没有-E( --regexp-extended) 选项则使用Basic正则表达式(不包括向后查找或向前查找)。

如果您计划使用逗号分隔值的其余字段,您可能需要考虑awk解析这些字段。您可以轻松获取指定-F字段分隔符和简单循环的所有字段。

$ awk -F', ' '{for (i = 1; i <= NF; i++) printf "field %d - %s\n", i, $i}' <<< $name
field 1 - ERROR 1: /home/rphillips/Desktop/empties/BN23_2303.tif
field 2 - band 1: Failed to compute statistics
field 3 - no valid pixels found in sampling.
Run Code Online (Sandbox Code Playgroud)

(您也可以使用循环内的条件来处理每个字段的进一步解析)

在 Bash 中 - 您只需要参数扩展

不要忽视树木的森林,因为您指定了bash,如果您只是想从 中提取文件名name,您所需要的只是删除子字符串的参数扩展(首先从右侧,然后从左侧),例如

tmp=${name%%,*}    ## trim to (and including) the 1st comma from the right
echo "/${tmp#*/}"  ## trim to and including the first / from the left
/home/rphillips/Desktop/empties/BN23_2303.tif
Run Code Online (Sandbox Code Playgroud)

(一种更有效的方法)

检查一下,如果您还有其他问题,请告诉我。