Return 数字范围内低于字符串模式匹配的值

Return Values Below String Pattern Match in Number Range

我需要匹配和 return 以下文本文件的第一个 line/row (UTC) 中低于数字范围 12-00 的值:

UTC  06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 00 01 02 03 04 05 06 
TMP  54 53 52 50 49 48 47 47 47 48 48 48 48 48 47 45 44 43 43 41 40 39 38 37 36

也就是说,匹配第 1 行中的 12 13 14 15 16 17 18 19 20 21 22 23 00 和第 2 行中的 returning 47 47 47 48 48 48 48 48 47 45 44 43 43

我的尝试:

cat some.text.file | head -n 3 | grep -A 1 '12.*.00' | tail -n 1

结果:

TMP  54 53 52 50 49 48 47 47 47 48 48 48 48 48 47 45 44 43 43 41 40 39 38 37 36

预期结果:

12 13 14 15 16 17 18 19 20 21 22 23 00
47 47 47 48 48 48 48 48 47 45 44 43 43

这可以一次性完成 awk:

awk 'NR == 1 {for (i=1; i<=NF; ++i) if ($i == "12") start = i; else if ($i == "00") stop = i} {for (i=start; i<=stop; ++i) printf "%s", $i (i < stop ? OFS : ORS)}' file

12 13 14 15 16 17 18 19 20 21 22 23 00
47 47 47 48 48 48 48 48 47 45 44 43 43

更具可读性的版本:

awk 'NR == 1 {
   for (i=1; i<=NF; ++i)
      if ($i == "12")
         start = i
      else if ($i == "00")
         stop = i
}
{
   for (i=start; i<=stop; ++i)
      printf "%s", $i (i < stop ? OFS : ORS)
}' file

我将按如下方式使用 GNU AWK 完成此任务,令 file.txt 内容为

UTC  06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 00 01 02 03 04 05 06 
TMP  54 53 52 50 49 48 47 47 47 48 48 48 48 48 47 45 44 43 43 41 40 39 38 37 36

然后

awk '/^UTC/{match([=11=],"12 13 14 15 16 17 18 19 20 21 22 23 00")}{print substr([=11=],RSTART,RLENGTH)}' file.txt

输出

12 13 14 15 16 17 18 19 20 21 22 23 00
47 47 47 48 48 48 48 48 47 45 44 43 43

说明:我使用 2 functions for working with stringsmatch 它确实设置了 RSTARTRLENGTH,然后 substr 得到那部分线或部分在它下面。第一个动作仅限于以 UTC 开头的行,第二个动作适用于所有行。

免责声明:此解决方案假定必须事先知道必须匹配的字符串

(在 gawk 4.2.1 中测试)

一般来说,对于这样的问题,您希望根据输入字段的某些映射输出一组字段,我发现最好创建一个数组,将输出字段编号映射到输入字段编号(out2in[] 下面)然后遍历该数组:

$ cat tst.awk
NR == 1 {
    for (inFldNr=2; $inFldNr!=0; inFldNr++) {
        if ( $inFldNr >= 12 ) {
            out2in[++numOutFlds] = inFldNr
        }
    }
    out2in[++numOutFlds] = inFldNr
}
{
    for (outFldNr=1; outFldNr<=numOutFlds; outFldNr++) {
        inFldNr = out2in[outFldNr]
        printf "%s%s", $inFldNr, (outFldNr<numOutFlds ? OFS : ORS)
    }
}

$ awk -f tst.awk file
12 13 14 15 16 17 18 19 20 21 22 23 00
47 47 47 48 48 48 48 48 47 45 44 43 43

上面假设在输入的第一行总是有一个终止字段编号00,如果不是这种情况,只需调整逻辑来处理它。

这可能适合您 (GNU sed):

sed -E 's/\s*$//;N;:a;/^12/!s/^.(.*\n).//;ta;/00\n/!s/.(\n.*).//;ta' file

启用扩展正则表达式 -E

Trim第一行末尾的空格。

追加下一行。

如果第一行的开头不是12,则从两行的开头删除一个字符。

如果第一行的末尾不是00,则从两行的末尾删除一个字符。

打印结果。