【问题标题】:Awk/Perl/Sed column substitution based on a text code基于文本代码的 Awk/Perl/Sed 列替换
【发布时间】:2013-05-17 23:37:49
【问题描述】:

我有一个包含以下内容的文本文件

L,4m,06/03/2013
L,33GJm,06/03/2013,G
L,44Bm,06/03/2013,B
L,4q,08/03/2013
J,4m,04/03/2013
J,3GU,04/03/2013,G
J,3jm,04/03/2013
J,3GJ,04/03/2013,G
J,44Bm,06/03/2013,B
J,34Bq,08/03/2013,B
M,4v,12/03/2013
D,3GU,12/03/2013,G
D,4B,11/03/2013,B
D,4m,12/03/2013
D,3GJ,13/03/2013,G
D,3GU,13/03/2013,G
D,4B,14/03/2013,B
D,4B,14/03/2013,B
D,34Bm,14/03/2013,B
L,33BUq,11/03/2013,B
L,3BJUq,11/03/2013,B
L,44Bq,14/03/2013,B
L,44Bq,14/03/2013,B
L,3Bq,15/03/2013,B
L,3q,15/03/2013
J,34Bjq,11/03/2013,B
J,33GUm,12/03/2013,G
J,4q,13/03/2013
J,33GUq,13/03/2013,G
J,33GUq,13/03/2013,G
J,4q,13/03/2013
M,3BU,18/03/2013,B
M,4B,18/03/2013,B
M,4B,18/03/2013,B
M,3GJ,19/03/2013,G
M,3GJ,19/03/2013,G
D,4B,22/03/2013,B
D,3BU,22/03/2013,B
L,34Bv,18/03/2013,B
L,3jm,19/03/2013
L,4m,19/03/2013
L,33GJm,19/03/2013,G
L,33GUm,19/03/2013,G
J,33BUm,18/03/2013,B
J,4m,18/03/2013
J,4B,18/03/2013,B
J,33BUm,18/03/2013,B
J,4q,22/03/2013
J,4q,22/03/2013
A,3GJ,28/03/2013,G
M,4B,27/03/2013,B
D,4B,25/03/2013,B
L,44Bq,25/03/2013,B
L,34Bq,25/03/2013,B
L,34Bq,25/03/2013,B
L,33BUa,26/03/2013,B
L,33BUq,26/03/2013,B
L,33BUq,26/03/2013,B
L,34Bq,27/03/2013,B
L,34Bq,27/03/2013,B
L,4B,27/03/2013,B
L,34Bq,27/03/2013,B
L,4a,28/03/2013

我想根据以下编码系统翻译第二列。

如果 $2 以 1 或 2 开头 - 将 $2 更改为优秀 如果 $2 包含 3BU 或 3GU - 将 $2 更改为 Good 如果 $2 包含 3BJ 或 3GJ - 将 $2 更改为 OK 如果 $2 以 4 开头 - 将 $2 更改为差 如果 $2 以 5 开头 - 更改 $2 太可怕了

我可以使用以下命令轻松找到 3BU 并将其更改为 Good

awk 'BEGIN{FS=",";OFS=","} {if ($2~ /3(B|G)U/)print $1,"Good",$3}' file | sponge file

虽然我使用所有其他非 3(B|G)U 行。我可以使用 if else 术语,尽管这看起来不优雅。我已经尝试使用 gensub 来解决问题

awk -F, '{gensub(/3(B|G)U/,Good,"",2)}1' file

但这会打印文件内容而不进行替换。任何提示

期望的输出

L,Poor,06/03/2013
L,Ok,06/03/2013,G
L,Poor,06/03/2013,B
L,Poor,08/03/2013
J,Poor,04/03/2013
J,Good,04/03/2013,G

perl 或 sed 单行代码也会有所帮助,因为此代码是 bash shell 脚本的一部分

【问题讨论】:

    标签: perl sed awk


    【解决方案1】:

    如果你想坚持使用 shell:

    (
        IFS=,
        while read -ra f; do     # pick more appropriate variable names
            case ${f[1]} in
                [12]*)    f[1]=Excellent ;;
                *3[BG]U*) f[1]=Good ;;
                *3[BG]J*) f[1]=OK ;;
                4*)       f[1]=Poor ;;
                5*)       f[1]=Terrible ;;
            esac
            echo "${f[*]}"
        done < file
    ) > tmp && mv tmp file
    

    我在子 shell 中运行它以本地化对 $IFS 的更改

    【讨论】:

      【解决方案2】:

      还有一个 sed 解决方案

      sed -e 's/\(^.,\)\(1\|2\)[^,]*/\1Excellent/g' -e 's/\(^.,\)3[BG]U[^,]*/\1Good/g' -e 's/\(^.,\)3[BG]J[^,]*/\1OK/g' -e 's/\(^.,\)4[^,]*/\1Poor/g' -e 's/\(^.,\)5[^,]*/\1Terrible/g' &lt;filename&gt;

      【讨论】:

        【解决方案3】:
        $ awk '
        BEGIN { FS=OFS="," }
        $2 ~ /^(1|2)/  { $2 = "Excellent" }
        $2 ~ /3(B|G)U/ { $2 = "Good" }
        $2 ~ /3(B|G)J/ { $2 = "OK" }
        $2 ~ /^4/      { $2 = "Poor" }
        $2 ~ /^5/      { $2 = "Terrible" }
        1
        ' foo.txt | head -n 10
        
        L,Poor,06/03/2013
        L,OK,06/03/2013,G
        L,Poor,06/03/2013,B
        L,Poor,08/03/2013
        J,Poor,04/03/2013
        J,Good,04/03/2013,G
        J,3jm,04/03/2013
        J,OK,04/03/2013,G
        J,Poor,06/03/2013,B
        J,34Bq,08/03/2013,B
        

        【讨论】:

        • 我不知道它是否更有效,但是一个字符类可以替换1个字符的交替:/^[12]//^3[BG]U/1
        • @glennjackman 我也这么认为,但我刚刚对 100k 个文件进行了一些测试,并且计时结果或多或少是等效的。我猜正则表达式引擎优化它了?但无论哪种方式,字符类肯定更具可读性。
        【解决方案4】:
        perl -pe 's{,(\w+)}{ $_ = /^[12]/ ?"Excellent" :/3[BG]U/ ?"Good" :/3[BG]J/ ?"OK" :/^4/ ?"Poor" :/^5/ ?"Terrible" :$_ for $v=$1; ",$v" }e'
        

        更易读的版本,

        s{,(\w+)}{
        
          for ($v = $1) {
            $_ = /^[12]/   ?"Excellent" 
                 :/3[BG]U/ ?"Good" 
                 :/3[BG]J/ ?"OK" 
                 :/^4/     ?"Poor" 
                 :/^5/     ?"Terrible" 
                 :$_;
          }
        
          ",$v";
        }e;
        

        【讨论】:

          猜你喜欢
          • 2018-07-02
          • 1970-01-01
          • 1970-01-01
          • 2020-04-27
          • 2015-10-25
          • 2013-11-11
          • 2017-06-16
          • 1970-01-01
          • 2021-12-07
          相关资源
          最近更新 更多