Awk 使用可变行字段逐列打印字段

Awk 使用可变行字段逐列打印字段,awk,Awk,我有一个命令,返回一个类似于的输出 ************* * something * ************* | Header | Title | Column1|Column2 | Column3 |Column4| Column5 |Column6|Column7| Column8 | ---------------------------

我有一个命令,返回一个类似于的输出

*************
* something *
*************

                                                     |     Header    |  Title  |
Column1|Column2         | Column3  |Column4| Column5 |Column6|Column7| Column8 |
--------------------------------------------------------------------------------
val1    val2             val3       x y      i j      1(a) 2  1(a) 2  val4
val5    val6             val7       w x y z  i j k    2(b) 2  1(b) 1  val8
..
..

Total lines: xx
例如,我只想打印column6,但由于输出不是按空格固定的变量字段,
awk'{print$x}'
对我来说不起作用。我需要一种按定义列(如第6列或第8列)打印输出的方法。也许从右边打印column6字段,从右边打印字段$5?是否有这样一种从右打印的方法,而不是从左打印所有命令计数字段的默认方法


任何帮助都将不胜感激。

为此请使用
NF

awk '{print $(NF-5)}'

这将打印第6列到最后一列,例如

我一直在解决类似的问题。假设Column6一直存在,您可以使用下面的冒号来查找索引

echo "Column1|Column2|Column6|Column8" | sed 's/Column6.*//;s/[^|]\+//g' | wc -c
然后,您可以简单地构造awk查询

X=$(echo ...)
SCRIPT="{ print \$${X}; }"
echo "Column1 |Column2 |Column6 |Column8" | awk "${SCRIPT}"
|Column6

在Gnu awk中重写

$ cat program.awk
BEGIN  { FS="|" }
$0 ~ c {                                # process record with header
    split($0,a,"|")                     # split to get header indexes
    for(i in a) {                       # loop all column names
        gsub(/^ *| *$/,"",a[i])         # trim space off
        if(a[i]==c) ci=i                # ci is the one              
    }
    while(i=index($0,FS)) {             # form FIXEDWIDTHS to separate fields
        FIELDWIDTHS = FIELDWIDTHS i " "
        $0=substr($0,i+1)
    }
}
ci && $ci !~ /^-+$/ && $0=$ci           # implicit printing
运行它:

$ awk -v c="Column6" -f program.awk file
1(a) 2  
2(b) 2  

如果要编辑输出列,请在
program.awk
中的最后一行进行编辑。例如,让我们设想一下,如果您想松开
列6
的括号部分,您可以使用
{sub(/\(.*)/,”);print}
为其创建一个动作部分。

那么,对于示例输入,您只想打印
1(a)2
2(b)2
,对吗,哪些列本身包含空格,并且前面的列也包含可变数量的空格?您不能依赖
1(a)2
的格式,因为您可能需要打印第4列(或第5列、第7列或第8列),这是否正确?你能确定管道在实线前的位置吗?括号()内的内容对我来说并不重要,括号()左右两侧括号外的数字是我试图从命令输出中提取出来的,即1和2。因为awk、sed和cut都是从左开始计数的字段,所以不能用awk、sed和cut提取第6、7和8列,除非我能找到一种方法让这些实用程序从右到左开始计数,因为从右到左计数的字段,由空格分隔的字段总是恒定的。希望这能解释我面临的问题。请用额外的信息更新问题,并包括您对样本数据的期望(确保描述和样本匹配)。您可能需要再包含几行数据。你在评论中提到了6-8;请确保您在更新中涵盖了相关基础。谢谢。抱歉说得含糊不清。示例数据如下所示;**************某物************标题标题第1列第2列第3列第4列第5列第6列第7列第8列第1(a)段2 val4 val5 val6 val7 w x y z i j k 2(b)2 1(b)1 val8。。总行数:XX正如我前面提到的,请更新问题-也就是说,使用编辑链接并更改问题的内容。不要破坏已经存在的内容,而是在问题中添加额外的信息。这样做的一个原因是,您可以格式化信息-这在注释中是无法做到的。对于
val5
行,应该打印第11列和第12列;对于
val1
行,应打印第8列和第9列。您是否可以依赖最后5个字段的结构尚不清楚-您可以打印
$(NF-5)
$(NF-4)
,但这并不确定。返回了一个致命错误;$cat dfile | awk'{print$(NF-5)}awk:cmd。行:1:(FILENAME=-FNR=1)致命:尝试访问字段-4只是玩它根据你的建议,似乎,我需要去掉页眉和页脚,只留下下面的内容;val1 val2 val3 x y i j 1(a)2 1(a)2 val4 val5 val6 val7 w x y z i j k 2(b)2 1(b)1 val8。。然后使用awk{print$(NF-5)}给了我一些接近我想要的东西,只是想知道是否有更简单、更快速的方法来提取()左边的数字,因为1和()之间没有空格(.不幸的是,它所做的只是打印标题;第1列|第2列|第3列|第4列|第5列|第6列|第7列|第8列()是我试图从命令输出中提取出来的,1和2没有打印出来。不幸的是,它只打印第6列,即()是我试图从命令输出中提取的,1和2没有打印出来。这种行为的原因在答案的正文第一行解释过。这个解决方案是重写。