以bash或awk格式化输出

时间:2014-07-23 11:21:12

标签: bash awk

我有以下输出

 Agnes               en_US    # Isn't it nice to have a computer that will talk to you?
 Albert              en_US    #  I have a frog in my throat. No, I mean a real frog!
 Bad News            en_US    # The light you see at the end of the tunnel is the headlamp of a fast approaching train.
 ...

我想要做的是将第一个字段存储在变量x中,将第三个字段存储在另一个变量y中;第一行的第一个字段是Agnes,第三个字段是Isn't it nice to have a computer that will talk to you?这样做的原因是能够使用for循环来执行{{1}的程序}和$x作为参数。

我想使用Bash命令和AWK完成此任务。你们会编写一个脚本,将第一个和第三个字段存储到变量中吗?

4 个答案:

答案 0 :(得分:2)

使用Bash:

#!/bin/bash

shopt -s extglob

while read -r line; do
    x=${line%%  *}
    y=${line##*([^#])+(#)*([[:blank:]])}
    # Do something with $x and $y.
    echo "$x|$y"
done

用法:

bash script.sh file

使用Awk:

#!/usr/bin/awk -f

NF {
    x = $0
    sub(/  .*$/, "", x)
    sub(/^[ \t]*/, "", x)
    y = $0
    sub(/^[^#]+[#]+[ \t]*/, "", y)
    # Do something with x and y.
    printf "%s|%s\n", x, y
}

用法:

awk -f script.awk file

输出:

Agnes|Isn't it nice to have a computer that will talk to you?
Albert|I have a frog in my throat. No, I mean a real frog!
Bad News|The light you see at the end of the tunnel is the headlamp of a fast approaching train.

答案 1 :(得分:2)

如果您确切知道这些字段是固定宽度的:

$ awk -v OFS='|' '{x=substr($0,1,20); y=substr($0,31); sub(/ +$/,"",x); sub(/^ +/,"",y); print x, y}' file
Agnes|Isn't it nice to have a computer that will talk to you?
Albert|I have a frog in my throat. No, I mean a real frog!
Bad News|The light you see at the end of the tunnel is the headlamp of a fast approaching train.

或者如果最后一个字段总是以#开头而且该行没有其他#

$ awk -F'# *' -v OFS='|' '{sub(/ *[^ ]+ *$/,"",$1); print $1, $2}' file
Agnes|Isn't it nice to have a computer that will talk to you?
Albert|I have a frog in my throat. No, I mean a real frog!
Bad News|The light you see at the end of the tunnel is the headlamp of a fast approaching train.

如果|对您不起作用,请选择您自己的分隔符,并通过设置IFS并使用read -r将其读入您喜欢的任何bash变量或数组中,例如:

$ awk -v OFS='|' '{x=substr($0,1,20); y=substr($0,31); sub(/ +$/,"",x); sub(/^ +/,"",y); print x, y}' file |
while IFS='|' read -r x y; do printf "x=%s\ny=%s\n\n" "$x" "$y"; done
x=Agnes
y=Isn't it nice to have a computer that will talk to you?

x=Albert
y=I have a frog in my throat. No, I mean a real frog!

x=Bad News
y=The light you see at the end of the tunnel is the headlamp of a fast approaching train.

这很可能不是最好的方法,你可能最好用awk编写脚本的其余部分。

通常会考虑GNU awk和FIELDWIDTHS这样的问题:

$ awk -v OFS='|' 'BEGIN{FIELDWIDTHS="20 10 999"} {for (i=1;i<=NF;i++) gsub(/^ +| +$/,"",$i); print $1, $3}' file
Agnes|Isn't it nice to have a computer that will talk to you?
Albert|I have a frog in my throat. No, I mean a real frog!
Bad News|The light you see at the end of the tunnel is the headlamp of a fast approaching train.

但恕我直言,对于这个特殊的2场问题,它没有用处。

答案 2 :(得分:0)

您可以将awkwhile循环一起使用:

while IFS=@ read -ra arr; do
   printf "<%s>\n" "${arr[@]}"
done < <(awk -F ' {3,}' -v OFS=@ '{print $1, $3}' file.txt)

<强>输出:

<Agnes>
<# Isn't it nice to have a computer that will talk to you?>
<Albert>
<#  I have a frog in my throat. No, I mean a real frog!>
<Bad News>
<# The light you see at the end of the tunnel is the headlamp of a fast approaching train.>

答案 3 :(得分:0)

另一种解决方案:

awk -F '#' '{ 
              x = substr($1,1,20); # Assume fixed width format
              y = $2;
              sub(/^[ \t]*/,"",x); sub(/[ \t]*$/,"",x); # trim white spaces
              sub(/^[ \t]*/,"",y); sub(/[ \t]*$/,"",y); # trim white spaces

              # At this point x hold user name, y its comment
              print x ":" y;
              }' datafile

在这种情况下,xy将为每一行保留正确的值。

如果您真的只想处理第一行,请更改为:

awk -F '#' 'NR == 1 { 
              x = substr($1,1,20); # Assume fixed width format
              y = $2;
              sub(/^[ \t]*/,"",x); sub(/[ \t]*$/,"",x); # trim white spaces
              sub(/^[ \t]*/,"",y); sub(/[ \t]*$/,"",y); # trim white spaces

              # At this point x hold user name, y its comment
              print x ":" y;
              }' datafile