2011-11-04 172 views
90

如何在包含管道符号|的字符串中拆分字符串。 我想将它们拆分成数组。如何在awk中将分隔字符串拆分为数组?

我试图

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

工作正常。如果我的字符串像"12|23|11"那么我该如何将它们拆分成一个数组?

+3

请注意,您的输出连接数组元素,没有分隔符。如果你希望用'OFS'分隔它们,在它们之间插入逗号,使得'print'将它们视为单独的参数。 – dubiousjim

回答

145

您是否尝试过:

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

不适合我:(是因为字符串的长度?因为,我的字符串长度是4000.任何想法 –

+0

@Mohamed Saligh,如果你在Solaris上,你需要使用*/usr/xpg4/bin/awk *,给定字符串长度。 –

+5

'不适合我'。回声值和分割之间的冒号设置为在'|'上分割错别字?祝大家好运 – shellter

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 

,所以我想它的工作毕竟..

+0

它不适合我:( –

+0

是因为字符串的长度?因为,我的字符串长度是4000.任何想法 –

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

应该工作。

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

请再具体些! “它不起作用”是什么意思? 邮政确切的输出(或错误信息),您的操作系统和awk版本:

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

或者,采用分体式:

% 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个字段。

+0

'(i = 0'或'对于(i = 1'? – PiotrNycz

+0

i = 0,因为我在++之后使用++ i(不是i ++)。 –

+1

好吧 - 我没有注意到这一点,我坚信更多的可读性是'for(i = 1; i < n; ++ i)'...... – PiotrNycz

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 
40

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 
::: 

让我们引用的手册页:

分裂(字符串数组[,fieldsep [,SEPS] )

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

相关问题