我编写了一个工作表达式,从有效的文本行中提取两条数据。第一个捕获组是包含句点的数字部分。第二个是该行的剩余字符,只要该行有效。如果数字部分以句点结尾或行以数字结尾,则该行无效。
1.1 the quick 1-1 (no match due to ending hypen and number)
11.2 brown fox jumped (should return '11.2' and 'brown fox jumped')
1.41.1 over the lazy (should return '1.41.1' and 'over the lazy')
2.1. dog (no match due to numerical section trailing period)
表达式 ^((?:[0-9]+\.)+[0-9]+) (.*)[^0-9]$
在各种测试中都有效正则表达式测试站点。
我的问题是...我未能调整此表达式以与循环文本行 ($L) 的 bash 脚本中的 sed 一起使用。
IFS=$'\t' read -r NUM STR < <(sed 's#^\(\(?:[0-9]\+\.\)\+[0-9]\+\) \(.*)[^0-9]$#\1\t\2#p;d' <<< $L )
下面的内容是有效的,我用重复的数字和句点替换了重复组的捕获。我不想这样做,因为它可以匹配以句点开头的行和连续的多个句点。它还丢失了捕获字符串的最后一个字符,但我希望我能弄清楚该部分。
FS=$'\t' read -r NUM STR < <(sed 's#^\([0-9\.]\+[0-9]\+\) \(.*[^0-9]\)$#\1\t\2#p;d' <<< $L )
请帮助我理解我做错了什么。谢谢。
最佳答案
一个 ERE 是:
^([0-9]+(\.[0-9]+)*) (.*[^0-9])$
其中 \1
和 \3
是感兴趣的捕获组
但我不确定使用 sed
+ read
是捕获变量中数据的最佳方法;你可以只使用 bash
内置函数来代替:
#!/bin/bash
while IFS=' ' read -r num str
do
[[ $num =~ ^([0-9]+(\.[0-9]+)*)$ && $str =~ [^0-9]$ ]] || continue
declare -p num str
done < input.txt
不过,此解决方案有一个副作用:read
将删除该行的前导、尾随和第一个中间空格++ 字符。
如果您需要这些空格,那么您可以匹配整行:
#!/bin/bash
regex='^([0-9]+(\.[0-9]+)*) (.*[^0-9])$'
while IFS='' read -r line
do
[[ $line =~ $regex ]] || continue
num=${BASH_REMATCH[1]}
str=${BASH_REMATCH[3]}
declare -p num str
done < input.txt
关于regex - 将重复的正则表达式模式捕获为一组,在 bash 脚本中使用 sed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73270483/