Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 查找某个关键字旁边的所有数字_Bash_Text Parsing - Fatal编程技术网

Bash 查找某个关键字旁边的所有数字

Bash 查找某个关键字旁边的所有数字,bash,text-parsing,Bash,Text Parsing,我有一个文本文件。它包含一些文本。文本由字符串和数字混合而成。我想查找关键字旁边出现的所有数字。 例如(这里的关键字是day): 今天真是美好的一天。明天我将和我的10个朋友一起吃3个比萨饼,下次我们将吃50天或19天 (这句话对任何想知道的人来说都是胡说八道)。 我想提取数字32、50和19 我是bash的新手,到目前为止,我可以从文件中读取内容并提取所有数字 echo $(grep -Eo '[0-9\]+' $i) 编辑2: 关键字必须是day。白天、白天和黑夜是不允许的。如果您的gre

我有一个文本文件。它包含一些文本。文本由字符串和数字混合而成。我想查找关键字旁边出现的所有数字。 例如(这里的关键字是
day
):

今天真是美好的一天。明天我将和我的10个朋友一起吃3个比萨饼,下次我们将吃50天或19

(这句话对任何想知道的人来说都是胡说八道)。 我想提取数字325019

我是bash的新手,到目前为止,我可以从文件中读取内容并提取所有数字

echo $(grep -Eo '[0-9\]+' $i)
编辑2:
关键字必须是day。白天、白天和黑夜是不允许的。如果您的
grep
支持PCRE(
-p
),例如GNU
grep
,请原谅误解:

grep -Po '\d+(?=\s+day\b)'
  • -
    o只获取匹配的部分

  • \d+
    匹配一个或多个数字

  • 零宽度正向前瞻(
    (?=\s+day\b)
    )匹配一个或多个空格,后跟字符串
    day
    ,然后是单词边界

示例:

% grep -Po '\d+(?=\s+day\b)' <<<"Today is really nice 32 day. Tomorrow I will eat 3 pizzas with 10 of my friends next time we will take 50 day or 19 day"
32
50
19
GNU awk中的
%grep-Po'\d+(?=\s+day\b):

$ awk -v RS='[ \n]' '{if(p~/[0-9]+/&&/^day/)print p;p=$0}' file
32
50
19

这里有一个选项可以不使用GNU的grep扩展:

grep -o '[0-9][0-9]* day\>' | awk '{print $1}'
但是,如果您想使用perl正则表达式(GNU
grep-p
就是这样做的),您可以始终使用perl:

perl -lne 'print $1 while /(\d+) day\b/g' foo.txt

对于纯bash解决方案,这里有一个:

#! /bin/bash
while read -r -a arr; do
    for (( i = 0; i < $(( ${#arr[@]} - 1 )); i += 1 )); do
        word=${arr[i]}
        next_word=${arr[$(( i + 1 ))]}
        [[ $word =~ ^[-0-9]+$ ]] &&
        [[ $next_word == "day" || $next_word == "day"[[:punct:]] ]] && 
        echo "$word"
    done
done < "/your/input/file" #or "$1" or whatever
#/bin/bash
而read-r-a arr;做
对于((i=0;i<$(${arr[@]}-1));i+=1));做
word=${arr[i]}
下一个单词=${arr[$((i+1))]}
[$word=~^[-0-9]+$]]&&
[[$next_word==“day”|$$next_word==“day”[:punt:]]]&&
回显“$word”
完成
完成
它逐行读取文件,创建每行的数组。 然后按数组的长度-1对数组进行迭代,检查每个项目是否为数字,然后检查下一个单词是否为带有标点符号或没有标点符号的单词
day


跳过已知行的简单优化留给读者作为练习

echo$()
在99%的时间里是多余的。请一般不要发布在循环中处理行的纯Bash解决方案,除非您在回答这些问题之前说,这种方法比使用合适的外部实用程序(如
grep
awk
慢得多)。在这种特定情况下,该解决方案不仅性能差,而且比
grep
awk
解决方案更复杂、更麻烦。如果你想展示Bash的功能,也可以这样说。举个例子:让我们创建一个包含1000个重复样本行的文件:
{for i in{1..1000};do echo'今天真是美好的32天。明天我将和10个朋友一起吃3个比萨饼,下次我们将花50天或19天';done}>file
,用你的代码,处理大约需要1.5秒。在我的机器上。使用
grep-Po'\d+(?=\s+day\b)
(heemayl的解决方案),大约需要0.03秒-一个50倍的时间。执行时间和比率会因许多因素而有所不同,但关键是:对于除小文件以外的所有文件,循环Bash解决方案都是错误的方法。问题没有标记为
grep
awk
,而是
Bash
,因此我提供了
Bash
解决方案。性能也不是问题。您可以从OP自己的解决方案尝试(涉及
grep
)中推断,其目的不是要有一个纯粹的Bash解决方案。在绝大多数情况下,人们使用
bash
标记的意思是:“我想要一个可以使用标准实用程序从命令行上的
bash
(shell)脚本/使用的解决方案。”@OlliK尽管答案提供了正确的输出,但它不是最优的。我认为可能提出的观点是,与其他解决方案相比,不披露此解决方案对性能的影响,人们可能会无意中发现这篇文章,并且对bash+utils了解有限的人可能会认为这是最好的解决方法,正如mklement0所解释的,不是。我不知道你们是否回答了我的问题,但我投了反对票。请评论我为什么抄袭你的答案。我比你早回答了,你已经知道了。嗯,我的回答比你的早一个小时。它就在时间戳上。我不担心否决票,因为我的票漏了
\b
是错误的,谢谢你提到这一点,但是抄袭别人的答案是荒谬的,我从来没有打过平手,也没有人指责你抄袭;他们只是指出你的答案和我的差不多。你是唯一提到抄袭答案的人。:)