Bash awk打印匹配分隔符

时间:2017-09-11 11:02:50

标签: awk

有没有办法用awk打印当前匹配的分隔符?

例如:

awk -F '["RESTART" | "FAILURE" | "WARNING" | [:blank:]]{2}' 'FNR > 4 { for (i=1; i<=NF; i++) print $i;}' file

示例输入

XX      XXXX   RESTART 6666  XX X
XXXX    XXXX   WARNING 8888  YYY YYY
XXX     XXXX   INFORM  7777  XXXX XX

示例输出(必须)

XX
XXXX
RESTART
6666
XX X
XXXX
XXXX
WARNING
8888
YYY YYY
XXX
XXXX
INFORM
7777
XXXX XX

示例输出(现在)

XX
XXXX
6666
XX X
XXXX
XXXX
8888
YYY YYY
XXX
XXXX
INFORM
7777
XXXX XX

我使用2个以上的空格作为列分隔符,但有些情况(RESTART 6666)或(WARNING 8888)其中两列没有两个空格分隔,这就是为什么我必须使用内容(RESTARTWARNING)作为分隔符,但如果我将内容用作分隔符,则不会显示,因此我想显示/打印使用的分隔符(如果是内容而不是空白)

主要问题是在一列中区分用作列分隔符的一个空格和用作字分隔符的一个空格。我无法影响我必须处理的文件。

3 个答案:

答案 0 :(得分:1)

<强> AWK:

awk '{gsub(/  +|\t/,"\n")} {print}' file | awk '/RESTART|WARNING|FAILURE/{gsub(/ /,"\n")}  {print}'

gsub(/ +|\t/,"\n"):用换行符\n替换“2个或多个空格OR \ t”。
这会将我们的文件转换为多行,其中每行可以由仅由单个空格分隔的多个单词组成。

/RESTART|WARNING|FAILURE/{gsub(/ /,"\n"):如果该行包含这三个字中的一个,那么将空格替换为\n

您还可以使用 sed

sed "s/\s\s\+/\n/g; s/\(RESTART\|WARNING\|FAILURE\) /\1\n/g"  file

对于较旧的sed版本(主要在MAC中):+可能不受支持,因此请将其修改为*

sed "s/\s\s\s*/\n/g; s/\(RESTART\|WARNING\|FAILURE\) /\1\n/g"  file

s/\s\s\+/\n/g:将2个或多个空格替换为单个\n
s/\(RESTART\|WARNING\|FAILURE\) /\1\n/g:用\n替换空格 三个例外

输入:

line one      hello hello   RESTART 6666  XX X
line two    hello hello   WARNING 8888  YYY YYY
line three  hello hello      INFORM  7777  XXXX XX

输出:

line one
hello hello
RESTART
6666
XX X
line two
hello hello
WARNING
8888
YYY YYY
line three
hello hello
INFORM
7777
XXXX XX

答案 1 :(得分:1)

这里有一个固定宽度字段的方法,可用于任何awk(当然,在Solaris上你应该使用/ usr / xpg4 / bin / awk的旧的awk / bin / awk除外):

$ cat tst.awk
{
    # identify the fields:
    nf = 0
    f[++nf] = substr($0,1,8)
    f[++nf] = substr($0,9,7)
    f[++nf] = substr($0,16,8)
    f[++nf] = substr($0,24,6)
    f[++nf] = substr($0,30)

    # remove leading/trailing white space from each field:
    for (i in f) {
        sub(/^[[:space:]]+/,"",f[i])
        sub(/[[:space:]]+$/,"",f[i])
    }

    # print the fields:
    for (i=1; i<=nf; i++) {
        print NR, i, "<" f[i] ">"
    }
    print "---"
}

$ awk -f tst.awk file
1 1 <XX>
1 2 <XXXX>
1 3 <RESTART>
1 4 <6666>
1 5 <XX X>
---
2 1 <XXXX>
2 2 <XXXX>
2 3 <WARNING>
2 4 <8888>
2 5 <YYY YYY>
---
3 1 <XXX>
3 2 <XXXX>
3 3 <INFORM>
3 4 <7777>
3 5 <XXXX XX>
---

如果您在Solaris上使用nawk,那么您必须将[[:space:]]替换为[ \t],因为它早于POSIX字符类但只是不使用nawk,请使用/ usr / xpg4 / bin / awk。

如果此方法适合您,可以修改它以使用循环而不是5个显式substr()调用。

答案 2 :(得分:0)

也许你可以使用GNU awk&#39; split seps https://www.gnu.org/software/gawk/manual/html_node/String-Functions.html告诉:

  

split(string,array [,fieldsep [,seps]])

     

seps是一个gawk扩展,seps [i]是array [i]和array [i + 1]之间的分隔符。