不使用 cut 获取行中的第一个模式匹配

不使用 cut 获取行中的第一个模式匹配

有一堆与此类似的文本(为了测试和使数据尽可能简单):

first 1 is the real 2 time the word matched 3 
appeared on the previous line but is 4 the fourth.
Every line can have more numbers 5 because numbers 6 are everywhere
I need to extract the number just after the word 7 that precedes 8

grep我正在测试提取单词后面数字的第一个匹配项的命令是:

grep -Eoi ' [0-9]{1}'

输出是:

 1
 2
 3
 4
 5
 6
 7
 8

期望的输出是:

 1
 4
 5
 7

不允许使用cut也不awk

答案1

我怀疑这是一种仅掌握 grep 的练习。纯 grep 解决方案是这样的:

在一行中:

echo "first 1 is the real 2 time the word matched 3 " |grep -Eo '[0-9]' |grep -m1 -E '[0-9]'

不幸的是,在第一个 grep 中使用grep -m1并没有给出所需的结果。

在包含多行的文件中,您必须使用循环:

while read -r line; do
grep -Eo '[0-9]' <<<"$line" |grep -m1 -E '[0-9]'
done < file.txt

或者在一个命令行中:

while read -r line; do grep -Eo '[0-9]' <<<"$line" |grep -m1 -E '[0-9]';done < a.txt

输出如所期望。

答案2

你被允许使用吗sed

$ sed 's/[^[[:digit:]]*\([[:digit:]]\).*/\1/' << EOF
> first 1 is the real 2 time the word matched 3 
> appeared on the previous line but is 4 the fourth.
> Every line can have more numbers 5 because numbers 6 are everywhere
> I need to extract the number just after the word 7 that precedes 8
> EOF
1
4
5
7

答案3

你可以使用 grep命令,首先匹配并返回第一个十进制数字序列之前的所有内容,然后匹配并仅返回数字:

grep -Eo '^[^0-9]*[0-9]{1,}' file | grep -Eo '[0-9]{1,}'

[注意:我之所以使用,{1,}是因为 AFAIK{1}是多余的,并且我假设您想要匹配十进制序列。]

如果您被允许使用 PCRE 模式,并且您支持它,则可以通过使用可变宽度后向断言grep在单个 中有效地执行相同的操作:grep\K

grep -Po '^[^0-9]*\K[0-9]+' file

或者(稍微更紧凑,使用 perl 样式\d表示十进制数字):

grep -Po '^[^\d]*\K\d+' file

或者说,自从你说你不是允许使用perl自身,您可以分成空格分隔的字段,然后找到第一个全数字字段:

perl -MList::Util=first -alne 'print first { /^\d+$/ } @F'

答案4

你可以试试这个:

grep -Eon ' [0-9]{1}' | sort -k1,1 -u

输出如下(不确定行号是否会破坏交易):

1: 1
2: 4
3: 5
4: 7

或者,此表达式将为您提供所需的输出:

grep -Eon ' [0-9]{1}' | sort -k1,1 -u | grep -o ' .*'

输出(您的输出示例包括前导空格):

 1
 4
 5
 7

相关内容