2016-01-14 110 views
3

我有一個文件foo具有以下數據:管道符號|在AWK字段分隔符

A<|>B<|>C<|>D 
1<|>2<|>3<|>4 

我想正確地訪問使用awk的每一列,但它不能正確解釋字段分隔符。

當我運行:

head foo | \ 
    awk 'BEGIN {FS="<|>"} {out=""; for(i=1;i<=NF;i++){out=out" "$i}; print out}' 

,而不是打印

A B C D 
1 2 3 4 

它打印

A | B | C | D 
1 | 2 | 3 | 4 

背後有什麼原因呢?

+0

只是一個提示:你可以在'awk'中使用'NR <11',而不是'head foo'。 – hek2mgl

回答

4

管道是一個正則表達式特殊字符,所以你需要用反斜槓來轉義它。但是這個反斜槓也是字符串文字的一個特殊字符,所以它需要再次轉義。所以,你最終的情況如下:

awk -F '<\\|>' '{$1=$1}1' 

awk 'BEGIN {FS="<\\|>"} {$1=$1}1' 

其原因語法如下解釋相當不錯:http://www.gnu.org/software/gawk/manual/gawk.html#Computed-Regexps。總之,表達式被解析兩次。

+0

@EdMorton您是指原始修訂版,還是由hek2mgl編輯?說實話,我只是在三個人問我後才發佈答案(見其他答案的評論),但我無法刪除它,因爲它被接受。 – user000001

+1

做了一個編輯來澄清這一點。雖然在我看來有趣的問題。 – user000001

6

awk讀取您的分隔符作爲正則表達式,「<>」。您必須轉義管道角色(兩次,看到動態正則表達式,如字段分隔符是scanned twice):"<\\|>"

你也可以指定字段分隔符作爲一個參數:

awk -F '<\\|>' '{out=""; for(i=1;i<=NF;i++){out=out" "$i}; print out}' <<< 'A<|>B<|>C<|>D' 
A B C D 

根據您的版本的awk,你也許可以僥倖逃脫只是單一轉義。對我來說,mawk 1.3.3適用於-F '<\|>'-F '<\\|>',而gawk 4.0.1需要-F '<\\|>'。我不完全確定POSIX awk要走哪條路,但在--posix模式下運行gawk也需要雙重轉義。

+1

可以這樣寫:'awk'BEGIN {FS =「<\\|>」} {$ 1 = $ 1} 1''或甚至'awk -F'<\|>''{$ 1 = $ 1} 1'' – user000001

+0

@ user000001爲什麼不把後者成爲答案?也想回答:)但它應該是'awk -F'<\\|>''$ 1 = $ 1'' – hek2mgl

+0

我試過這個最初。取消引用|無法正常工作。它說以下內容 awk:warning:轉義序列'\ |'視爲普通的'|'我不太明白 – Andrew

3

順便說一句,也sed這裏可以使用:

sed 's/<|>/ /g' file 

如果你想「列入」 head命令:

sed -n '1,10s/<|>/ /gp' file