在同一文件中逐块获取值

在同一文件中逐块获取值

我有一个名为“SAMPLE.txt”的文件,其内容如下,

P1
10,9:6/123456
P2
blah blah
P1
10,9:5/98765
P2
blah
blah
P1
blah blah
P2

我想要一个输出文件“RESULT.txt”,

Value1:123456
Value2:98765
Value3:NULL

我需要先获取 P1 和 P2 部分之间的内容,然后找到 10,9*/ 的值,并将其保存为另一个值。如果某个 P1-P2 块不包含此值,我想将其保存为“NULL”。

如何在 shell/awk 中编写上述代码?

我对脚本编写很陌生。

答案1

这有效并且完全可移植:

sed '\|^P1.*|!d;s||Value:|
     :n
     N;\|\nP2|!bn
     s|:.*\n10,9[^/]*/|:|
     s|\n.*||;s|:$|:NULL|' 

流程如下:

  1. 首先它寻址^P1

  2. 如果当前行!不匹配,则会d将其删除。

  3. 如果是,则替换P1Value:

  4. 然后它设置:next 标签并拉入Next 行。

  5. 如果\nP2没有!找到,则b返回到:next 标签并重复尝试,直到出现为止。

  6. 然后,它会删除:.*\n10,9直到第一个出现的/字符为止的所有出现的字符。

  7. 它删除第一个\n可用的 ewline 和所有后续字符。

  8. 如果最后一个字符是:后面的冒号,Value则插入字符串NULL

第 6 步和第 7 步使它起作用 - 在第 6 步中,它删除了\n所需数字字符串之前的 ewline,但如果不存在,那么下一个\newline 将是紧随其后的那一行Value:,因此一切进入步骤 7。

这是在行动中:

sed '\|^P1.*|!d;s||Value:|
     :n
     N;\|\nP2|!bn
     s|:.*\n10,9[^/]*/|:|
     s|\n.*||;s|:$|:NULL|' <<\DATA
P1
10,9:6/123456
P2
blah blah
P1
10,9:5/98765
P2
blah
blah
P1
blah blah
P2
DATA

输出:

Value:123456
Value:98765
Value:NULL

答案2

使用perl(尽管将整个文件放入内存中):

 perl -0777 -ne 'while (/P1\n(.*?)\nP2/gs) {
   printf "Value%d:%s\n", ++$n, $1 =~ /^10,9.*\// ? $'\'': "NULL"}'

答案3

一个perl办法:

$ perl -F'/' -alne '
    if (/P1/../P2/ and $_ !~ /^P/) {
        print "Value@{[++$i]}:",$F[1]?$F[1]:"NULL";
    }
' file
Value1:123456
Value2:98765
Value3:Null

解决方案awk

$ awk -F'/' '/P2/{f=0};/P1/{f=1;next};f{print "Value"++i":"($2?$2:"Null")}' file
Value1:123456
Value2:98765
Value3:Null

答案4

非常感谢大家。这是最终解决我的问题的一段代码。

nawk -v fname="${filename}" -F '/|:' '

    function isnum(x){return(x==x+0)}

    /P1/,/P3/{
            # Found start increment i reset variables go to next line
            if(/P1/){
                   ++i 
                   fid ="" 
                   count++
                   next
                }

            # Found end validate variable and print go to next line
            if(/P3/){
                printf "%s|",count
                printf "%s|",isnum(fid)?fid:"NULL"
                  next 
                }
            if(!fid && /36,59:*/)
                {
                    fid = $NF
                }
        ' ${filename} >>output.txt

但现在我遇到了另一个问题,我为此创建了一个单独的线程。

如果你们能帮忙的话,这是链接。

https://stackoverflow.com/questions/24277167/finding-and-replacing-text-inside-awk-block?noredirect=1#comment37509363_24277167

相关内容