【问题标题】:Replacing columns of a CSV with a string using awk and gsub使用 awk 和 gsub 将 CSV 的列替换为字符串
【发布时间】:2021-06-16 18:11:56
【问题描述】:

我有一个类似于以下内容的输入 csv 文件:

Name,Index,Location,ID,Message
Alexis,10,Punggol,4090b43,Production 4090b43
Scott,20,Bedok,bfb34d3,Prevent
Ronald,30,one-north,86defac,Difference 86defac
Cindy,40,Punggol,40d0ced,Central
Eric,50,one-north,aeff08d,Military aeff08d
David,60,Bedok,5d1152d,Study

我想使用awkgsub 编写一个bash shell 脚本,将ID 列下的6-7 个字母数字字符长字符串替换为“xxxxx”,并在单独的.csv 文件中输出。

现在我有:

#!/bin/bash
awk -F ',' -v OFS=',' '{gsub(/^([a-zA-Z0-9]){6,7}/g, "xxxxx", $4);}1' input.csv > output.csv

但是我从运行bash myscript.sh input.csv 得到的输出没有任何意义。 output.csv 文件如下所示:

Name,Index,Location,ID,Message
Alexis,10,Punggol,4xxxxx9xxxxxb43,Production 4090b43
Scott,20,Bedok,bfb34d3,Prevent
Ronald,30,one-north,86defac,Difference 86defac
Cindy,40,Punggol,4xxxxxdxxxxxced,Central
Eric,50,one-north,aeffxxxxx8d,Military aeff08d
David,60,Bedok,5d1152d,Study

但预期的输出 csv 应如下所示:

Name,Index,Location,ID,Message
Alexis,10,Punggol,xxxxx,Production 4090b43
Scott,20,Bedok,xxxxx,Prevent
Ronald,30,one-north,xxxxx,Difference 86defac
Cindy,40,Punggol,xxxxx,Central
Eric,50,one-north,xxxxx,Military aeff08d
David,60,Bedok,xxxxx,Study

【问题讨论】:

    标签: awk


    【解决方案1】:

    使用您显示的示例,请尝试以下代码:

    awk -F ',[[:space:]]+'  -v OFS=',\t' '
    {
      sub(/^([a-zA-Z0-9]){6,7}$/, "xxxxx", $4)
      $1=$1
    }
    1
    ' Input_file | column -t -s $'\t'
    

    说明: 将字段分隔符设置为逗号、空格,然后在此处将输出字段分隔符设置为逗号制表符。然后在第 4 个字段中用 xxxxx 替换字母数字的值(6 到 7 次)从开始到结束。最后打印当前行。然后将awk程序的输出发送到column命令,使其按照所示的OP示例进行。

    编辑:如果您的 Input_file 现在按照已编辑的示例仅由 , 分隔,请尝试以下操作。

    awk -F ',' -v OFS=',' '
    {
      sub(/^([a-zA-Z0-9]){6,7}$/, "xxxxx", $4)
    }
    1
    ' Input_file
    

    注意:OP 已经从旧版本安装了最新版本的 awk,这些代码有帮助。

    【讨论】:

    • 是在这种情况下将字段分隔符设置为逗号、空格和逗号制表符的原因,因为我展示了示例,因为在我的实际 csv 文件中,条目之间没有逗号或制表符。我只是将其格式化为帖子以使其更具可读性
    • @bakedgoods,如果你有一个名为 csv 格式的文件,它应该用逗号分隔。根据您显示的示例,您需要在输出中很好地对齐,因此将输出分隔符保持为 ,\t 将使分隔符成为逗号选项卡。然后将它传递给列命令将使它看起来像你在最终输出恕我直言中想要的样子。
    • 不幸的是代码不起作用。我得到的输出看起来像Name,Index,Location,ID,Message Alexis,10,Punggol,4090b43,Production 4090b43 Scott,20,Bedok,bfb34d3,Prevent Ronald,30,one-north,86defac,Difference 86defac Cindy,40,Punggol,40d0ced,Central Eric,50,one-north,aeff08d,Military aeff08d David,60,Bedok,5d1152d,Study
    • @bakedgoods,这是您展示的示例的测试代码,您的实际文件是否与展示的示例相同?
    • 我尝试使用跟随我的样本的测试文件,但我仍然得到原始 csv,ID 下的字段未更改
    【解决方案2】:

    您的答案的简短版本如下:

    $ awk 'BEGIN{FS=OFS=","}(FNR>1){$4="xxxxxx"}1' file
    

    这会将第 4 列中的所有条目替换为“xxxxxx”。

    如果您只想更改第 4 列的前 6 到 7 个字符(而不是如果只有 5 个字符,则有两种方法:

    $ awk 'BEGIN{FS=OFS=","}(FNR>1)&&(length($4)>5){$4="xxxxxx" substr($4,8)}1' file
    $ awk 'BEGIN{FS=OFS=","}(FNR>1)&&{sub(/.......?/,"xxxxxx",$4)}1' file
    

    这里,我们将 123456abcde 替换为 xxxxxxabcde

    为什么你的脚本会失败:

    除了方法错误之外,我将尝试解释以下命令的作用:gsub(/([a-zA-Z0-9]){6,7}/g,"xxxxx",$4)

    符号/abc/g 是有效的 awk 语法,但它并没有按照您的预期执行。符号/abc/ 是一个ERE 标记(扩展的正则表达式)。在这一点上,符号g 只不过是一个未定义的变量,它默认为空字符串或零,具体取决于它的用法。 awk 现在将尝试通过首先执行/abc/ 来执行操作/abc/g,这意味着:如果我当前的记录($0)与正则表达式“abc”匹配,则返回1,否则返回0。所以它将/abc/g转换为0g,这意味着将g的内容连接到数字0。为此,它将数字0 转换为字符串"0" 并将其与空字符串g 连接。最后,您的gsub 命令等同于gsub("0","xxxxx",$4),表示将所有零替换为“xxxxx”。

    为什么你总是得到gsub("0","xxxxx",$4) 而从来没有得到gsub("1","xxxxx",$4)。原因是您的初始正则表达式从不匹配完整记录/行中的任何内容 ($0)。您的 reguar 表达式为 /^([a-zA-Z0-9]){6,7}/,虽然有些行以 6 或 7 个字符开头,但您的 awk 很可能无法识别扩展的正则表达式表示法 '{m,n}' ,这使其失败。如果您使用 gnu awk,则使用 -re-interval 时输出会有所不同,旧版本的 GNU awk 默认情况下未启用。

    【讨论】:

      【解决方案3】:

      我试图找出你的代码为什么会这样,为了简单起见,我举了一个例子,只关注你使用过的gsub

      awk 'BEGIN{id="4090b43"}END{gsub(/^([a-zA-Z0-9]){6,7}/g, "xxxxx", id);print id}' emptyfile.txt
      

      输出是

      4xxxxx9xxxxxb43
      

      在第一个参数中删除 g 之后

      awk 'BEGIN{id="4090b43"}END{gsub(/^([a-zA-Z0-9]){6,7}/, "xxxxx", id);print id}' emptyfile.txt
      

      输出是

      xxxxx
      

      所以正则表达式后跟g 导致故障。我无法在 GNU AWK 手册中找到相关段落 g/ 之后应该做什么。

      (在 gawk 4.2.1 中测试)

      【讨论】:

        猜你喜欢
        • 2017-05-20
        • 1970-01-01
        • 2021-01-29
        • 2014-06-20
        • 2013-02-17
        • 1970-01-01
        • 1970-01-01
        • 2013-09-05
        • 2012-06-07
        相关资源
        最近更新 更多