【问题标题】:How to take multiple argument in bash and pass them to awk?如何在 bash 中获取多个参数并将它们传递给 awk?
【发布时间】:2016-11-11 11:47:33
【问题描述】:

我正在编写一个替换前导/尾随空格的函数 从列中,如果列中没有值,则将其替换为 null。 功能对于一列工作正常,但我如何修改它以用于多列。

功能:

#cat trimfunction
#!/bin/bash
function trim
{
vCol=$1                                                    ###input column name
vFile=$2                                                   ###input file name
var3=/home/vipin/temp                                      ###temp file
awk -v col="${vCol}" -f /home/vipin/colf.awk ${vFile} > $var3 ###operation
mv -f $var3 $vFile                                         ###Forcefully mv
}

AWK 脚本:

#cat colf.awk
#!/bin/awk -f
BEGIN{FS=OFS="|"}{
  gsub(/^[ \t]+|[ \t]+$/, "", $col)                        ###replace space from 2nd column
}
{if ($col=="") {print $1,"NULL",$3} else print $0}         ###replace whitespace with NULL

输入文件:第二列中的前导/尾随/空白

#cat filename.txt
1| 2016-01|00000321|12
2|2016-02 |000000432|13
3|2017-03 |000004312|54
4|  |000005|32
5|2017-05|00000543|12

脚本:

#cat script.sh

    . /home/vipin/trimfunction
    trim 2 filename.txt

输出文件:在第二列中删除了前导/尾随/空白

#./script.sh
#cat filename.txt
1|2016-01|00000321|12
2|2016-02|000000432|13
3|2017-03|000004312|54
4|NULL|000005
5|2017-05|00000543|12

如果输入文件如下所示 - (第二个中的白色/前导/尾随空格 和文件的第 5 列)

1|2016-01|00000321|12|2016-01 |00000
2|2016-02 |000000432|13| 2016-01|00000
3| 2017-03|000004312|54|  |00000
4|  |000005|2016-02|0000
5|2017-05 |00000543|12|2016-02 |0000

如何实现低于输出 - (所有前导/尾随空格修剪和 在第 2 列和第 5 列中用 NULL 替换空格)类似于修剪 2 5 filename.txt trim 2 5 filename.txt ###将两列名称作为 输入

1|2016-01|00000321|12|2016-01|00000
2|2016-02|000000432|13|2016-01|00000
3|2017-03|000004312|54|NULL|00000
4|NULL|000005|2016-02|0000
5|2017-05|00000543|12|2016-02|0000

【问题讨论】:

  • 您真的想针对特定列还是只针对每个空列执行此操作?在您的示例中包含一个空列,如果发生这种情况,您不希望对其进行修改。顺便说一句,非常明确的问题!
  • @EdMorton - 仅适用于我将通过的特定列:trim 2 5 filename.txt OR trim 4 6 119 filename.txt

标签: bash function unix awk arguments


【解决方案1】:

这会按你说的做:

$ cat tst.sh
file="${!#}"
cols=( "$@" )
unset cols[$(( $# - 1 ))]

awk -v cols="${cols[*]}" '
BEGIN {
    split(cols,c)
    FS=OFS="|"
}
{
    for (i in c) {
        gsub(/^[[:space:]]+|[[:space:]]+$/,"",$(c[i]))
        sub(/^$/,"NULL",$(c[i]))
    }
    print
}' "$file"

$ ./tst.sh 2 5 file
1|2016-01|00000321|12|2016-01|00000
2|2016-02|000000432|13|2016-01|00000
3|2017-03|000004312|54|NULL|00000
4|NULL|000005|2016-02|0000
5|2017-05|00000543|12|2016-02|0000

但如果您真正想要的是对所有字段而不是特定字段进行操作,那么当然有更简单的解决方案。

顺便说一句,永远不要使用cmd file > tmp; mv tmp file,而是始终使用cmd file > tmp && mv tmp file(注意&&),因此只有在命令成功时才会覆盖原始文件。另外 - 总是引用你的 shell 变量,除非你有一个非常具体的目的而不这样做并且完全理解所有的含义,所以使用"$file",而不是$file。谷歌一下。

【讨论】:

    【解决方案2】:

    您可以将要修改的列列表作为参数传递。创建文件

    $ cat trim.awk
    
    BEGIN {
        split(c, a)
        FS = OFS = "|"
    }
    
    {
        for (i in a) {
            i = a[i]
            gsub(/^[ \t]+|[ \t]+$/, "", $i)
            if (!length($i)) $i = "NULL"
        }
        print
    }
    

    $ cat filename.txt
    
    1|2016-01|00000321|12|2016-01 |00000
    2|2016-02 |000000432|13| 2016-01|00000
    3| 2017-03|000004312|54|  |00000
    4|  |000005|2016-02|0000
    5|2017-05 |00000543|12|2016-02 |0000
    

    用法:

    awk -v c="2 5" -f trim.awk filename.txt 
    

    【讨论】:

      【解决方案3】:

      如果您只想管理前导/尾随空格,那么您可能不想做所有(AWK 代码)。

      cat q1.txt | tr -s ' ' | sed 's/|\ |/|NULL|/g' | sed 's/\ //g' 应该可以。

      分解
      tr -s ' ' : 将多个空格挤成一个
      sed 's/|\ |/|NULL|/g' : 替换所有“| |” with "|NULL|"
      sed 's/\ //g' : 用空字符串替换所有空格。

      【讨论】:

      • 当然你会想要为此编写所有的 awk 代码。你还会做什么?您的命令行有一个 UUOC,无缘无故地转义空白字符,当空格/空字段是一行中的第一个/最后一个时会失败,将空格链冗余压缩到单个空格,然后删除该空格,这将是不可取的删除字段中间的所有空格,将无法根据需要将空字段 (||) 替换为 NULL,并且不会按照 OP 的要求关注特定字段。
      • 同意冗余。 OP使用了cat,因此我使用了cat,开始的答案以免责声明开头,如果只需要空白管理(实现给定的输出),那么答案才合适。在将命令发布到此处之前,我尝试了 7 行,其中特别添加了 2 行的第一个和最后一个空格。
      • 该命令不可能根据需要用NULL|NULL|NULL 替换||(3 个空字段或其中任何一个字段)。再试一次。
      猜你喜欢
      • 2012-01-23
      • 1970-01-01
      • 2020-12-24
      • 1970-01-01
      • 1970-01-01
      • 2020-03-21
      • 1970-01-01
      • 2012-05-09
      • 1970-01-01
      相关资源
      最近更新 更多