使用 awk 将一行分割为单个空格而不是多个空格

使用 awk 将一行分割为单个空格而不是多个空格

我正在尝试分割一条我无法控制其格式的行。如果参数 7 和 8 丢失,它们可能会被空格替换,所以我最终会得到,

field1 field2 field3 field4 field5 field6   field9

目前,在这种情况下,字段 9 被读取为字段 7。大量搜索使我相信以下内容应该有效,但它不起作用。这可能是我的一些小语​​法错误,但我似乎无法发现它。

word1=`echo $LINE | awk 'BEGIN { FS="[ ]" } ; { print $9 }'`

答案1

LINE 参数没有被引用,因此在inwordsplitting扩展时发生,并且在接收任何输入时,您有 7 个(如 shell 所见),全部由一个空格分隔。您希望 echo 将其作为一个输出(再次,如 shell 所见),以便在 awk 处理它之前,行中的空白不会被破坏。这就是引用参数所防止的。$LINEecho $LINEawkwordsword

# How you want it to be given to awk:
$ printf '<%s> ' "$LINE"; echo
<field1 field2 field3 field4 field5 field6   field9> 
# Your attempt:
$ printf '<%s> ' $LINE; echo
<field1> <field2> <field3> <field4> <field5> <field6> <field9> 

请注意字段 6 和字段 9 之间多余的空格是如何消失的。

您应该始终引用扩展,不引用扩展比引用扩展更有可能破坏某些内容。

答案2

在处理可变输入长度时,awk 中一个非常有用的参数是 NF,即字段数。

lastword=`echo $LINE | awk '{ print $NF }'`

这将始终打印最后一列,无论缺少哪一列。如果中间的某些字段丢失,从最后一个字段倒数也很有效。

一个示例文件,其中缺失/空列填充空格,如您的示例所示:

line1 field1 field2 field3 field4 field5 field6 field7 field8 field9
line2 field1 field2 field3 field4 field5 field6  field8 field9
line3 field1 field2 field3 field4 field5   field8 field9

awk '{print $1 " " $2 " " $(NF-1) " " $NF}' file

    line1 field1 field8 field9
    line2 field1 field8 field9
    line3 field1 field8 field9

答案3

要做到这一点ksh93

set -f
IFS='  ' # two spaces
set -- $LINE
printf '%s\n' "$9"

将空格加倍可以消除特殊行为,即空格序列被视为一个,并且前导空格和尾随空格被忽略,如 中所示zsh

答案4

就我而言,我决定先将其通过管道传输tr。只需将空格映射到不太可能出现在我们的输入中的字符(在本例中为 bell code \a):

❯ echo 'a b  d' | tr ' ' '\a' | awk -F'\a' '{print "1="$1, "2="$2, "3="$3, "4="$4}'
1=a 2=b 3= 4=d

请注意第三个字段$3现在为空。


一小时后再次见面。

相关内容