如何使用循环提取可变模式之间的线条

如何使用循环提取可变模式之间的线条

我有一个 csv 文件,其中包含这样的模式列表

文件1:

aaa;bbb      
ccc;ddd
eee;fff
...

文件2:

aaa2222222222222222
3333333333333333333
4444444444444444444
bbb555555555555555
8888888888888888888
ccc5555555555555555
5555555555555555555
0000000000000000000
ddd6666666666666666

如何在命令中使用文件 1 中每行的 2 个模式(例如aaa& )来匹配并打印文件 2 中匹配模式之间的行,保存输出,然后将命令替换为要重复的下一对模式过程?bbbsed -n '/aaa/,/bbb/p'

我期望的输出是

333333333333333         
444444444444444   

保存到新文件,因为它们是aaa&之间的行bbb

ccc然后使用循环查找&ddd等之间的下一组行。

答案1

这可能就是您正在寻找的内容,假设 file1 中指定的或 file2 中没有重叠或嵌套范围或重复的开始/结束字符串:

$ cat tst.awk
BEGIN { FS=";" }

NR==FNR {
    begs2ends[$1] = $2
    next
}

end == "" {
    for ( beg in begs2ends ) {
        if ( index($0,beg) == 1 ) {
            end = begs2ends[beg]
            close(out)
            out = "out" (++cnt) ".txt"
            break
        }
    }
    next
}

{
    if ( index($0,end) == 1 ) {
        end = ""
    }
    else {
        print $0 " > " out
    }
}

$ awk -f tst.awk file1 file2
3333333333333333333 > out1.txt
4444444444444444444 > out1.txt
5555555555555555555 > out2.txt
0000000000000000000 > out2.txt

完成初始测试后,更改print $0 " > " out为实际创建单独的输出文件。print > out

答案2

我喜欢 awk,因为这样只需要一个进程。使用 sed 可能需要低效的 shell 循环和多个 sed 命令。

awk -F ';' '
    NR==FNR{        #For the first file given as an argument
        k++         #Increment k
        pat1[k]=$1  #Add 1st field (before ;) to pat1 array
        pat2[k]=$2  #Add 2nd field (after ;) to pat2 array
        next        #Start new cycle with the next line
    }

    {
        for (i=1;i<=k;i++){
            if ($0~pat2[i]){flag[i]=0}           #If line has terminating pattern
            if (flag[i]){print>(pat1[i]pat2[i])} #If flag=1, print this line to a file
            if ($0~pat1[i]){flag[i]=1}           #If line has starting pattern
        }
    }
' patterns.csv input

注意不要颠倒参数:首先是模式文件,然后是输入文件。

输入示例:

aaa2
3333
4444
bbb5
8888
ccc5
0000
aaa7
7777
bbb7
ddd6

创建两个文件,内容为:

$ cat aaabbb
3333
4444
7777
$ cat cccddd
0000
aaa7
7777
bbb7

答案3

使用 Gnu sed,我们从 file1 的内容动态准备 sed 代码,然后将生成的代码应用到 f​​ile2。这些文件是静默创建的。

sed -Ee 's|;|/,/|' \
     -e 's|(.).*(.)|/&/{\n\t//!w FILE_\1\2\n}|' file1 \
|  sed -nf - file2
more FILE_?? 

答案4

file2content="$( < file2 )";
while read p;do 
    ((${#p}))&&sed -n "/${p%;*}/,/${p##*;}/p" <<< "${file2content}"|grep -v "^${p%;*}\|^${p##*;}" > "${p%;*}_${p##*;}"; 
done <file1

相关内容