2011-11-04 361 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()的返回值(即數組中的 元素的數目)。

相關問題