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