Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.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
Regex 从文本文件中的重复范围模式获取特定行_Regex_Perl_Sed_Awk_Pattern Matching_Bash - Fatal编程技术网

Regex 从文本文件中的重复范围模式获取特定行

Regex 从文本文件中的重复范围模式获取特定行,regex,perl,sed,awk,pattern-matching,bash,Regex,Perl,Sed,Awk,Pattern Matching,Bash,哇,这听起来很复杂的标题,但我想它不是很复杂 我的文本文件基本上是这样的布局: Stimulus ... ... ... ... Response Stimulus ... ... ... ... Response 我使用sed获取中间的所有信息,然后进一步提取我需要的信息 sed -n -e '/Stimulus/,/Response/ p' 但是,有时参与者没有响应,在这种情况下,文件如下所示: Stimulus ... ... ... ... Stimulus ... ... ...

哇,这听起来很复杂的标题,但我想它不是很复杂

我的文本文件基本上是这样的布局:

Stimulus ...
...
...
...
Response
Stimulus ...
...
...
...
Response
我使用sed获取中间的所有信息,然后进一步提取我需要的信息

sed -n -e '/Stimulus/,/Response/ p'
但是,有时参与者没有响应,在这种情况下,文件如下所示:

Stimulus ...
...
...
...
Stimulus ...
...
...
...
Response
在这种特殊情况下,我的脚本将无法获得我想要的内容。因此,我正在寻找一种方法来提取信息,当且仅当pattern1后面跟着pattern2,而不是pattern1


如果我不清楚,请告诉我。我非常乐意提供进一步的信息。

一种肮脏的方法,尽管在我的测试中似乎有效,但可能是反转文件内容,从
响应
搜索到
刺激
,然后再次反转结果

假设以下输入数据:

Stimulus 1...
...
...
...
Stimulus 2...
...
...
...
Response 2
Stimulus 3...
...
...
...
Response 3
Stimulus 4...
...
...
...
Stimulus 5...
命令:

tac infile | sed -ne '/Response/,/Stimulus/ p' | tac -
收益率:

Stimulus 2...
...
...
...
Response 2
Stimulus 3...
...
...
...
Response 3

编辑:例如带有独立的
响应
部分的示例。需要过滤两次(基于OP的评论):


另一个选项是切换到
perl
及其触发器(范围运算符):

假设输入文件为:

Stimulus 1...
...
...
...
Stimulus 2...
...
...
...
Response 2
Stimulus 3...
...
...
...
Response 3
Stimulus 4...
...
...
...
Stimulus 5...
它产生:

Stimulus 2...
...
...
...
Response 2
Stimulus 3...
...
...
...
Response 3
这是一个纯粹的解决方案:

tmp=()
while read l; do
  [[ $l =~ ^Stimulus ]] && tmp=("$l") && continue
  [ ${#tmp[@]} -eq 0 ] && continue
  tmp+=("$l")
  [[ $l =~ ^Response ]] && printf "%s\n" "${tmp[@]}" && tmp=()
done <infile
输出:

Stimulus 2
...
Response 2
Stimulus 3
...
Response 3
这里有一个纯粹的解决方案,它试图最小化愚蠢的副作用:

#!/bin/bash

out=()

while read -r l; do
   case "$l" in
       Stimulus*) out=( "$l" ) ;;
       Response*) ((${#out[@]}!=0)) && { printf "%s\n" "${out[@]}" "$l"; out=(); } ;;
       *) ((${#out[@]}!=0)) && out+=( "$l" ) ;;
   esac
done < infile
#/bin/bash
out=()
而read-rl;做
大写“$l”
刺激*)输出=(“$l”);;
响应*)(${out[@]}!=0))&&{printf“%s\n”${out[@]}“$l”;out=();};;
*)(${out[@]}!=0))&&out+=(“$l”);;
以撒
完成<填充
它还处理有
反应
但没有
刺激

更新以处理孤立反应的情况

awk'
/响应/{
如果(p==1){
对于(;kReally,GNU的工作非常简单,单向,没有多余的管道和工具:

输入文件:

Stimulus 1... bad bad bad Stimulus 2... ... ... ... Response 2 Stimulus 3... ... ... ... Response 3 Stimulus 4... bad bad bad bad Stimulus 5... ... ... ... ... Response 5 bad bad bad bad Response 6 bad bad bad 刺激1。。。 坏的 坏的 坏的 刺激2。。。 ... ... ... 答复2 刺激3。。。 ... ... ... 答复3 刺激4。。。 坏的 坏的 坏的 坏的 刺激5。。。 ... ... ... ... 答复5 坏的 坏的 坏的 坏的 答复6 坏的 坏的 坏的
和输出:

$sed -n 'H;/^Stimulus/{h;d};/^Response/{x;s/^Response//;tk;p;:k;d}' file Stimulus 2... ... ... ... Response 2 Stimulus 3... ... ... ... Response 3 Stimulus 5... ... ... ... ... Response 5 $sed-n'H;/^stimultium/{H;d};/^Response/{x;s/^Response//;tk;p;:k;d}文件 刺激2。。。 ... ... ... 答复2 刺激3。。。 ... ... ... 答复3 刺激5。。。 ... ... ... ... 答复5
我的GNU代码是:


awk'{a[++i]=$0};/^Response/&&a[1]!~/^Response/{for(k=1;kdoes
,/stimultium/,/Response | stimultium/
有效?嗯……可能不行。这通常可以通过一个awk脚本来解决,该脚本为这两个值设置一个flg,当这两个值都为真时,做你需要做的事情。祝你好运。将在每个
响应上输出内容,即使之前没有
stimultium
。此外,正则表达式也太过了:
[[$l=Response*]
就足够了。@gniourf\u gniourf:如果没有以
刺激开始的行,你能告诉我输出是什么吗?
我猜是空行。:)当然,你可以使用全局匹配。我更喜欢。你在每个
响应
上输出
tmp
数组,不管发生什么,即使之前没有任何
刺激
。在这方面,你没有完全回答OP。请在@Birei的回答中查看OP的注释。@gniouf\gniouf:你是对的。这是解决方案原来的问题是n。我更正了,thx!我们现在几乎有了相同的算法。
+1
:)
。优雅。将测试它是否会回来。我测试了它,但出现了一个小问题,因为不仅存在孤立的刺激部分,而且存在孤立的响应部分。然而,两次执行该过程可以实现以下目的:tac infle | sed-ne'/response/,/stimulation/p'| tac-| sed-ne'/stimulation/,/response/p'),从而使它抽搐-抽搐!
#!/bin/bash

out=()

while read -r l; do
   case "$l" in
       Stimulus*) out=( "$l" ) ;;
       Response*) ((${#out[@]}!=0)) && { printf "%s\n" "${out[@]}" "$l"; out=(); } ;;
       *) ((${#out[@]}!=0)) && out+=( "$l" ) ;;
   esac
done < infile
awk '
/Response/ { 
    if (p==1) {
        for(;k<length(a);) {
            print a[++k]
        }
        print $0
    }
    delete a;k=p=0
} 
/Stimulus/ {
    if (p==1) {
        delete a; i=0
    }
    p=1
} 
p { a[++i]=$0 }' log
sed -n 'H;/^Stimulus/{h;d};/^Response/{x;s/^Response//;tk;p;:k;d}' file
Stimulus 1... bad bad bad Stimulus 2... ... ... ... Response 2 Stimulus 3... ... ... ... Response 3 Stimulus 4... bad bad bad bad Stimulus 5... ... ... ... ... Response 5 bad bad bad bad Response 6 bad bad bad $sed -n 'H;/^Stimulus/{h;d};/^Response/{x;s/^Response//;tk;p;:k;d}' file Stimulus 2... ... ... ... Response 2 Stimulus 3... ... ... ... Response 3 Stimulus 5... ... ... ... ... Response 5
awk '{a[++i]=$0};/^Response/ && a[1] !~ /^Response/ {for (k=1; k<=i; k++) {print a[k]}};/^Stimulus|^Response/ { delete a; i=0; a[++i]=$0}' file