如何在awk中将分隔的字符串拆分为数组?

时间:2011-11-04 13:10:29

标签: string unix awk split

如何在字符串中包含管道符号|时对其进行拆分。 我想将它们分成阵列。

我试过

echo "12:23:11" | awk '{split($0,a,":"); print a[3] a[2] a[1]}'

哪个工作正常。如果我的字符串类似于"12|23|11",那么如何将它们拆分成数组呢?

10 个答案:

答案 0 :(得分:200)

你试过了吗?

echo "12|23|11" | awk '{split($0,a,"|"); print a[3],a[2],a[1]}'

答案 1 :(得分:82)

要将字符串拆分为awk中的数组,我们使用函数split()

 awk '{split($0, a, ":")}'
 #           ^^  ^  ^^^
 #            |  |   |
 #       string  |   delimiter
 #               |
 #               array to store the pieces

如果没有给出分隔符,则使用FS,默认为空格:

$ awk '{split($0, a); print a[2]}' <<< "a:b c:d e"
c:d

我们可以提供一个分隔符,例如:

$ awk '{split($0, a, ":"); print a[2]}' <<< "a:b c:d e"
b c

这相当于通过FS

进行设置
$ awk -F: '{split($0, a); print a[1]}' <<< "a:b c:d e"
b c

在gawk中,您还可以将分隔符作为正则表达式提供:

$ awk '{split($0, a, ":*"); print a[2]}' <<< "a:::b c::d e" #note multiple :
b c

甚至通过使用第四个参数来查看每个步骤的分隔符:

$ awk '{split($0, a, ":*", sep); print a[2]; print sep[1]}' <<< "a:::b c::d e"
b c
:::

让我们引用man page of GNU awk

  

split(string,array [,fieldsep [,seps]])

     

字符串分成由 fieldsep 分隔的片段,并将片段存储在数组中,并将分隔符字符串存储在 seps 数组。第一部分存储在array[1]中,第二部分存储在array[2]中,依此类推。第三个参数 fieldsep 的字符串值是一个正则表达式,用于描述将字符串拆分的位置(就像 FS 可以是描述位置的正则表达式)拆分输入记录)。如果省略 fieldsep ,则使用 FS 的值。 split()返回创建的元素数。 seps gawk扩展程序,seps[i]array[i]array[i+1]之间的分隔符字符串。如果 fieldsep 是单个空格,则任何前导空格都会进入seps[0],任何尾随空格都会进入seps[n],其中 n 是返回值split()的数量(即数组中元素的数量)。

答案 2 :(得分:15)

请更具体!你说“它不起作用”是什么意思? 发布确切的输出(或错误消息),您的操作系统和awk版本:

% awk -F\| '{
  for (i = 0; ++i <= NF;)
    print i, $i
  }' <<<'12|23|11'
1 12
2 23
3 11

或者,使用split:

% awk '{
  n = split($0, t, "|")
  for (i = 0; ++i <= n;)
    print i, t[i]
  }' <<<'12|23|11'
1 12
2 23
3 11

编辑:在 Solaris 上,你需要使用 POSIX awk( / usr / xpg4 / bin / awk )才能正确处理4000个字段。

答案 3 :(得分:3)

echo "12|23|11" | awk '{split($0,a,"|"); print a[3] a[2] a[1]}'

答案 4 :(得分:2)

echo "12|23|11" | awk '{split($0,a,"|"); print a[3] a[2] a[1]}'

应该有用。

答案 5 :(得分:2)

我不喜欢echo "..." | awk ...解决方案,因为它调用了不必要的forkexec系统调用。

我更喜欢Dimitre的解决方案,但有点麻烦

awk -F\| '{print $3 $2 $1}' <<<'12|23|11'

或者更短的版本:

awk -F\| '$0=$3 $2 $1' <<<'12|23|11'

在这种情况下,输出记录放在一起,这是一个真实的条件,因此它被打印出来。

在这种特定情况下,stdin重定向可以通过设置内部变量来实现:

awk -v T='12|23|11' 'BEGIN{split(T,a,"|");print a[3] a[2] a[1]}'

我使用了很长一段时间,但在中,这可以通过内部字符串操作来管理。在第一种情况下,原始字符串由内部终止符分割。在第二种情况下,假设字符串始终包含由一个字符分隔符分隔的数字对。

T='12|23|11';echo -n ${T##*|};T=${T%|*};echo ${T#*|}${T%|*}
T='12|23|11';echo ${T:6}${T:3:2}${T:0:2}

所有情况下的结果都是

112312

答案 6 :(得分:2)

实际上,awk具有一个称为“输入字段分隔符变量” link的功能。这是如何使用它。它实际上不是数组,但是使用内部$变量。要分割一个简单的字符串,会更容易。

echo "12|23|11" | awk 'BEGIN {FS="|";} { print $1, $2, $3 }'

答案 7 :(得分:1)

笑话? :)

echo "12|23|11" | awk '{split($0,a,"|"); print a[3] a[2] a[1]}'

怎么样?

这是我的输出:

p2> echo "12|23|11" | awk '{split($0,a,"|"); print a[3] a[2] a[1]}'
112312

所以我猜它毕竟有用..

答案 8 :(得分:0)

我知道这是一个古老的问题,但我认为也许有人喜欢我的把戏。特别是由于此解决方案不限于特定数量的项目。

# Convert to an array
_ITEMS=($(echo "12|23|11" | tr '|' '\n'))

# Output array items
for _ITEM in "${_ITEMS[@]}"; do
  echo "Item: ${_ITEM}"
done

输出将是:

Item: 12
Item: 23
Item: 11

答案 9 :(得分:0)

挑战:解析并存储带有空格的拆分字符串,并将它们插入到变量中。

解决方案:最简单的选择是将字符串列表转换为数组,然后将其解析为带有索引的变量。这是一个如何转换和访问数组的示例。

示例:解析每一行的磁盘空间统计:

sudo df -k | awk 'NR>1' | while read -r line; do
   #convert into array:
   array=($line)

   #variables:
   filesystem="${array[0]}"
   size="${array[1]}"
   capacity="${array[4]}"
   mountpoint="${array[5]}"
   echo "filesystem:$filesystem|size:$size|capacity:$capacity|mountpoint:$mountpoint"
done

#output:
filesystem:/dev/dsk/c0t0d0s1|size:4000|usage:40%|mountpoint:/
filesystem:/dev/dsk/c0t0d0s2|size:5000|usage:50%|mountpoint:/usr
filesystem:/proc|size:0|usage:0%|mountpoint:/proc
filesystem:mnttab|size:0|usage:0%|mountpoint:/etc/mnttab
filesystem:fd|size:1000|usage:10%|mountpoint:/dev/fd
filesystem:swap|size:9000|usage:9%|mountpoint:/var/run
filesystem:swap|size:1500|usage:15%|mountpoint:/tmp
filesystem:/dev/dsk/c0t0d0s3|size:8000|usage:80%|mountpoint:/export