我正在尝试分割一条我无法控制其格式的行。如果参数 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 处理它之前,行中的空白不会被破坏。这就是引用参数所防止的。$LINE
echo $LINE
awk
words
word
# 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
现在为空。
一小时后再次见面。