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

Moh*_*igh 141 unix string awk split

如何在字符串中包含管道符号时拆分|它.我想将它们拆分为数组.

我试过了

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

哪个工作正常.如果我的字符串是那样的"12|23|11"话我怎么把它们分成一个数组呢?

Cal*_*dru 234

你有没有尝试过:

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

  • '不适合我'.特别是在回声值和拆分设置之间用冒号分隔'|'??? 错字?祝你们好运. (5认同)
  • @Mohamed Saligh,如果您使用的是Solaris,则需要使用* / usr / xpg4 / bin / awk *(给定字符串长度)。 (2认同)
  • 最好有一些语法解释。 (2认同)
  • 这在GNU awk中不起作用,因为`split`的第三个参数是正则表达式,而`|`是特殊符号,需要进行转义.使用`split($ 0,a,"\ |")` (2认同)
  • @WhiteWind:“确保”`|`被视为字符而不是特殊符号的另一种方法是将其放在`[]`之间:即`split($0, a, "[|]")`#在某些情况下,我比“\|”更喜欢这个,特别是正则表达式的某些变体(perl vs grep vs .. other?)可以有“|” 按字面解释和“\|” 被视为正则表达式分隔符,而不是相反的... ymmv (2认同)

fed*_*qui 107

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

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

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

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

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

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

这相当于通过以下方式设置FS:

$ awk -F: '{split($0, a); print a[1]}' <<< "a:b c:d e"
b c
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

让我们引用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()(即,数组中元素的数量).


Dim*_*lov 15

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

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

或者,使用拆分:

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

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

  • 好的 - 我没注意到这一点.我坚信更可读的是'for(i = 1; i <= n; ++ i)`... (3认同)

Tru*_*ueY 7

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

我更喜欢稍微扭曲的 Dimitre 解决方案

awk -F\| '{print $3 $2 $1}' <<<'12|23|11'
Run Code Online (Sandbox Code Playgroud)

或者更短的版本:

awk -F\| '$0=$3 $2 $1' <<<'12|23|11'
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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}
Run Code Online (Sandbox Code Playgroud)

在所有情况下的结果是

112312
Run Code Online (Sandbox Code Playgroud)


Sve*_*ven 7

实际上awk有一个称为“输入字段分隔符变量”链接的功能。这是如何使用它。它并不是真正的数组,但它使用内部 $ 变量。对于分割一个简单的字符串来说更容易。

echo "12|23|11" | awk 'BEGIN {FS="|";} { print $1, $2, $3 }'
Run Code Online (Sandbox Code Playgroud)


due*_*l0r 6

玩笑?:)

怎么样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
Run Code Online (Sandbox Code Playgroud)

所以我想它毕竟有效..


Qor*_*ani 6

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

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

# Output array items
for _ITEM in "${_ITEMS[@]}"; do
  echo "Item: ${_ITEM}"
done
Run Code Online (Sandbox Code Playgroud)

输出将是:

Item: 12
Item: 23
Item: 11
Run Code Online (Sandbox Code Playgroud)


cod*_*ict 5

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

应该管用。