在awk中从字符串中删除前导和尾随空格

70

我试图从以下input.txt的第二列中删除前导和尾随空格:

Name,Order
Trim,working
cat,cat1

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

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

这将产生以下输出:

名称,订单  
修剪,工作
猫,猫1

前导和尾随空格未被移除。

8个回答

101
如果您想在仅包含逗号的行中修剪所有空格,并使用awk,则以下方法适用于您:
awk -F, '/,/{gsub(/ /, "", $0); print} ' input.txt

如果您只想删除第二列中的空格,请将表达式更改为:
awk -F, '/,/{gsub(/ /, "", $2); print$1","$2} ' input.txt

请注意,gsub将第二个表达式中的字符替换为第一个表达式中的字符,并在作为第三个参数的变量中进行原地修改。换句话说,在完成操作后,$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

1
请问您能否解释一下这个? - Marjer
3
查看@EdMorton的答案,它提供了一个单一的gsub解决方案。它还使用空格字符类,这是更好的做法。 - codeforester
Ed Morton的答案在这里 - codeforester
使用正则表达式:gsub(/^[ \t]+/,"",$2) - H S Rathore
2
这不是正确的答案,因为它删除了所有空格,而不仅仅是前导和尾随的空格。 - Peter
显示剩余6条评论

39

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

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 命令,通过使用 ^$ 锚点仅删除前导和尾随空格的方式。更复杂,但非常准确。 - Floris
1
我只是直接地想到了这个,感谢对Ganz Ricanz的详细解释。 - BMW
2
请随意改进您的答案,写下您所做的解释(或复制我的)。我认为您的答案应该被接受 - 但当它是“完整的”时,它总是更好。 - Floris
1
是的,而且命令会更简单。awk '$1=$1' infile > outfile - BMW
挑剔 - 这只会移除空格和制表符,而不是所有的空白字符(包括换行、回车、分页和垂直制表符)。另外,在评论中awk '$1=$1' 将在 $1 包含 0 时失败,所以不要这样做 - 如果你想从 CSV 中的所有字段中去除空格,应该使用 awk -F'[[:space:]]*,[[:space:]]*' -v OFS=',' '{$1=$1; gsub(/^[[:space:]]+|[[:space:]]+$/,"")} 1' - Ed Morton
显示剩余3条评论

22

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

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

22

警告:@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

在我看来,sed是这个任务的最佳工具。但是,这里提供了一个使用awk的解决方案,因为你要求用它:

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

另一个简单的解决方案是使用 tr -d 命令来删除所有空格:

cat input.txt | tr -d ' '

虽然我的回答的主要观点是展示 sedawk 更适合这个任务,因为它是一个文本编辑任务,但是 awk 脚本应该可以工作。我已经测试过了。有什么问题吗? - hek2mgl
你的 sed 命令似乎也无法移除尾随空格。只需在末尾加上 > output.txt,然后在文本编辑器中打开结果,你就会看到... - Floris
第一列之前没有尾随空格。任务更多的是:删除逗号后面的空格。 - hek2mgl
第二列末尾有多余空格。引用问题中的话:“我试图删除第二列开头和结尾的空格”。 - Floris
让我们在聊天中继续这个讨论:http://chat.stackoverflow.com/rooms/43225/discussion-between-floris-and-hek2mgl - Floris
显示剩余6条评论

5

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

', *' - 用于前导空格

' *,' - 用于尾随空格

同时用于前导和尾随:

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

未能从第二列中删除尾随空格。相反,它会从第一列中删除尾随空格。 - Geoff

2

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

$ cat -A input
^I    Name, ^IOrder  $
  Trim, working  $
cat,cat1^I  

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

1
好的,很简洁。你能修改一下代码,使其只修剪第二列吗(根据问题)? - Floris
失败,因为它删除了两列中的所有空格,并附加了错误的“$”符号。 - Geoff

2
以下似乎有效:
awk -F',[[:blank:]]*' '{$2=$2}1' OFS="," input.txt

失败并添加了不必要的逗号。 - Geoff

-1

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

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

添加另一个字段,例如awk '{print $1$2$3}' /tmp/input.txt将捕获两个空格集(最多三个单词在第二列),并且如果少于两个也不会出错。

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


失败得很惨,我甚至不想解释,但是试试“多个空格,这里”。 - Geoff
再次强调,此特定解决方案仅假定实际问题指定了两列之间的一个空格集。如果你认为使用复杂的gsub正则表达式替换比简单的awk打印语句更容易,我甚至不会试图解释你错在哪里。 - Andrew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接