在awk或nawk中,如何使用最后一次出现的管道字符作为字段分隔符,给我2个字段?

时间:2015-07-28 14:42:48

标签: regex awk nawk

我宁愿不使用仅限gawk的功能,因为我需要在各种UNIX风格上运行它,并不是所有的都有gawk。我有一个包含这样的行的文件:

^myfile\..*\.(pork|beef)$|send -d j
^myfile\..*\.(chicken|turkey|quail)$|send -d q
^myfile\..*\.cheese$|send -d u

有时,但并非总是如此,第一个字段包含一个或多个管道字符。最后一个管道之后的字符可以可靠地称为字段2。

3 个答案:

答案 0 :(得分:2)

我不确定这是否完全可移植,但我认为是:

awk '{
    # Find the position of the last "|" in the line.
    p=match($0, /\|[^|]*$/)

    # "Split" the line into two fields around that position.
    a[1]=substr($0, 1, p-1)
    a[2]=substr($0, p+1)

    printf "[%s] [%s]\n", a[1], a[2]
}' file.in

正如Ed Morton在评论中指出的那样,p这里的使用是不必要的,因为awk match函数还将RSTART变量设置为正则表达式匹配的字符串中的位置所以上面也可以这样写:

awk '{
    # Find the last "|" in the line.
    match($0, /\|[^|]*$/)

    # "Split" the line into two fields around that position (using the RSTART variable from the match() call).
    a[1]=substr($0, 1, RSTART-1)
    a[2]=substr($0, RSTART+1)

    printf "[%s] [%s]\n", a[1], a[2]
}' file.in'

事实上,有效执行此完全任务是awk Grymoirematch()的示例。

答案 1 :(得分:1)

You could just set FS to $|:

$ awk -F'[$][|]' '{printf "[%s$] [%s]\n", $1, $2}' file
[^myfile\..*\.(pork|beef)$] [send -d j]
[^myfile\..*\.(chicken|turkey|quail)$] [send -d q]
[^myfile\..*\.cheese$] [send -d u]

You can tack the $ back onto the end of $1 if you like:

$ awk -F'[$][|]' '{$1=$1"$"; printf "[%s] [%s]\n", $1, $2}' file
[^myfile\..*\.(pork|beef)$] [send -d j]
[^myfile\..*\.(chicken|turkey|quail)$] [send -d q]
[^myfile\..*\.cheese$] [send -d u]

Another approach if you prefer would be:

$ awk '{f1=f2=$0; sub(/\|[^|]*$/,"",f1); sub(/.*\|/,"",f2); printf "[%s] [%s]\n", f1, f2}' file
[^myfile\..*\.(pork|beef)$] [send -d j]
[^myfile\..*\.(chicken|turkey|quail)$] [send -d q]
[^myfile\..*\.cheese$] [send -d u]

答案 2 :(得分:0)

你也可以这样做(例如我选择标签作为新的分隔符):

awk -vRS='[|]' -vORS='' 'NR>1{printf /\n/?"\t":"|"}1' file