【问题标题】:Trim leading and trailing spaces from a string in awk从awk中的字符串中修剪前导和尾随空格
【发布时间】:2014-01-03 06:10:16
【问题描述】:

我正在尝试删除下面input.txt 的第二列中的前导和尾随空格:

Name, Order  
Trim, working
cat,cat1

我已经使用下面的awk 删除了第二列中的前导和尾随空格,但它不起作用。我错过了什么?

awk -F, '{$2=$2};1' input.txt

输出如下:

Name, Order  
Trim, working
cat,cat1

前导和尾随空格不会被删除。

【问题讨论】:

    标签: shell unix awk


    【解决方案1】:

    如果您想修剪所有空格,仅在有逗号的行中,并使用awk,那么以下内容将适合您:

    awk -F, '/,/{gsub(/ /, "", $0); print} ' input.txt
    

    如果你只想删除第二列中的空格,请将表达式更改为

    awk -F, '/,/{gsub(/ /, "", $2); print$1","$2} ' input.txt
    

    请注意,gsub// 中的字符替换为第三个参数的变量中的第二个表达式 - 并且这样做了 in-place - 换句话说,当它完成时,$0(或$2) 已被修改。

    完整解释:

    -F,            use comma as field separator 
                   (so the thing before the first comma is $1, etc)
    /,/            operate only on lines with a comma 
                   (this means empty lines are skipped)
    gsub(a,b,c)    match the regular expression a, replace it with b, 
                   and do all this with the contents of c
    print$1","$2   print the contents of field 1, a comma, then field 2
    input.txt      use input.txt as the source of lines to process
    

    编辑 我想指出@BMW 的解决方案更好,因为它实际上只使用两个连续的gsub 命令修剪前导和尾随空格。在给予信任的同时,我会解释它是如何工作的。

    gsub(/^[ \t]+/,"",$2);    - starting at the beginning (^) replace all (+ = zero or more, greedy)
                                 consecutive tabs and spaces with an empty string
    gsub(/[ \t]+$/,"",$2)}    - do the same, but now for all space up to the end of string ($)
    1                         - ="true". Shorthand for "use default action", which is print $0
                              - that is, print the entire (modified) line
    

    【讨论】:

    • 你能解释一下吗?
    • 查看@EdMorton 对单个gsub 解决方案的回答。它还使用字符类作为空间,这是更好的做法。
    • 艾德莫顿的回答是here
    • 使用了正则表达式.. gsub(/^[ \t]+/,"",$2)
    • 这不是正确答案,因为它会删除所有空格,而不仅仅是前导和尾随。
    【解决方案2】:

    删除第二列中的前导和尾随空格

    awk 'BEGIN{FS=OFS=","}{gsub(/^[ \t]+/,"",$2);gsub(/[ \t]+$/,"",$2)}1' input.txt
    

    一个 gsub 的另一种方式:

    awk 'BEGIN{FS=OFS=","} {gsub(/^[ \t]+|[ \t]+$/, "", $2)}1' infile
    

    【讨论】:

    • 我喜欢您通过在两个单独的 gsub 命令中使用 ^$ 锚点来仅删除前导和尾随空格的方式。更复杂,但在金钱上。
    • 我只是直接认为,感谢Ganz Ricanz的详细解释
    • 随时通过写下你所做的解释来改进你的答案(或复制我的)。我认为你的答案应该被接受——但当它“完整”时总是更好。
    • 这是唯一可以正常工作的答案,所以它应该是公认的答案。
    • 是的,命令会更简单。 awk '$1=$1' infile > outfile
    【解决方案3】:

    @Geoff 的警告:请参阅下面的注释,此答案中只有一个建议有效(尽管在两列中)。

    我会使用sed:

    sed 's/, /,/' input.txt
    

    这将删除, 之后的前导空格。 输出:

    Name,Order
    Trim,working
    cat,cat1
    

    更一般的可能如下,它可能会删除, 之后的多个空格和/或制表符:

    sed 's/,[ \t]\?/,/g' input.txt
    

    由于全局修饰符/g,它也适用于两列以上


    @Floris 在讨论中询问了一种解决方案,该解决方案可以删除每列(甚至是第一个和最后一个)中的尾随和结尾空格,同时不删除列中间的空格:

    sed 's/[ \t]\?,[ \t]\?/,/g; s/^[ \t]\+//g; s/[ \t]\+$//g' input.txt
    

    *@Geoff 编辑,我已将输入文件名附加到此文件名,现在它只删除所有前导和尾随空格(尽管来自两列)。此答案中的其他建议不起作用。但是尝试:“这里之前有多个空格和2个空格”*


    IMO sed 是完成这项工作的最佳工具。但是,这里有一个awk 的解决方案,因为您已经提出了要求:

    awk -F', ' '{printf "%s,%s\n", $1, $2}' input.txt
    

    另一个删除所有空格的简单解决方案是tr -d

    cat input.txt | tr -d ' '
    

    【讨论】:

    • 我认为您当前的 awk 解决方案不会删除 尾随 个空格...?
    • 虽然我回答的要点是表明 sed 比 awk 更适合这项工作 - 因为它是一项文本编辑任务,但 awk 脚本应该可以工作。我已经测试过了。这有什么问题?
    • 您的sed 命令似乎也没有删除尾随空格。只需将> output.txt放在最后,在文本编辑器中打开结果,您将看到...
    • 第一列之前没有尾随空格。任务更多:去掉,之后的空格
    • 第二列末尾的尾随空格。引用问题“我正在尝试删除第二列中的前导和尾随空格
    【解决方案4】:

    我刚遇到这个。正确答案是:

    awk 'BEGIN{FS=OFS=","} {gsub(/^[[:space:]]+|[[:space:]]+$/,"",$2)} 1'
    

    【讨论】:

      【解决方案5】:

      只需使用正则表达式作为分隔符:

      ', *' - 用于前导空格

      ' *,' - 用于尾随空格

      对于前导和尾随:

      awk -F' *,? *' '{print $1","$2}' input.txt
      

      【讨论】:

      • 未能从第 2 列中删除尾随空格。而是从第 1 列中删除尾随空格。
      【解决方案6】:

      最简单的解决方案可能是使用tr

      $ cat -A input
      ^I    Name, ^IOrder  $
        Trim, working  $
      cat,cat1^I  
      
      $ tr -d '[:blank:]' < input | cat -A
      Name,Order$
      Trim,working$
      cat,cat1
      

      【讨论】:

      • 美观紧凑。你可以修改它,让它只修剪第二列(根据问题)吗?
      • 失败,因为它从两列中删除了所有空格,并附加了虚假的“$”。
      【解决方案7】:

      以下似乎有效:

      awk -F',[[:blank:]]*' '{$2=$2}1' OFS="," input.txt
      

      【讨论】:

      • 失败并添加虚假逗号
      【解决方案8】:

      如果可以安全地假设第二列中只有一组空格(这是原始示例):

      awk '{print $1$2}' /tmp/input.txt

      添加另一个字段,例如awk '{print $1$2$3}' /tmp/input.txt 将捕获两组空格(第二列中最多三个单词),如果更少则不会中断。

      如果您有不确定(大量)用空格分隔的单词,我会使用前面的建议之一,否则这个解决方案是您使用 awk 找到的最简单的解决方案。

      【讨论】:

      • 严重失败,我什至不会尝试解释,而是尝试“多个空格,并且在这里”。
      • 再一次,这个特定的解决方案假定两列之间只有一组空格,由实际问题指定。如果你想假装一个复杂的 gsub 正则表达式替换比一个简单的 awk 打印语句“更容易”,我什至不会试图解释你为什么错了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-01
      • 2011-06-03
      • 2013-03-04
      • 2022-08-14
      • 1970-01-01
      • 2014-10-30
      相关资源
      最近更新 更多