如何使用 awk 命令将第 n 个到第 m 个字段清空?

Pri*_*riB 6 sed awk perl

我想用AWK解决下面的问题。

如果使用 sed 或 Perl 等语言可以使用任何其他解决方案,那也将不胜感激。

下面是输入:

U,N,UNIX,000,A,5
N,P,SHELL,111,B,6
I,M,UNIX,222,C,7
X,Y,BASH,333,D,8
P,R,SCRIPT,444,E,9
Run Code Online (Sandbox Code Playgroud)

我想要的输出如下:

U,N,,,A,5
N,P,,,B,6
I,M,,,C,7
X,Y,,,D,8
P,R,,,E,9
Run Code Online (Sandbox Code Playgroud)

另请注意:我不知道每行的字段总数。我只知道字段 3 和 4 是空白的。

Wil*_*ard 14

要将awk命令中从第 n 个到第 m 个的所有字段可伸缩地清空,您不应该对这些值进行硬编码;你应该使用“for”循环:

awk 'BEGIN { FS = ","; OFS = ","} {for (i = 3; i <= 4; i++) { $i = "" }; print}' inputfile
Run Code Online (Sandbox Code Playgroud)

如果要清空不同的范围,请调整上述代码中的值“3”和“4”。


解释:

BEGIN { ... }在查看文件的任何行之前处理该块。

OFS设置输出字段分隔符,并FS设置输入字段分隔符。我们希望它们都是逗号。

for循环就像C语法。在这种情况下它会执行以下{ code block }i作为3和4为。

$i,因为它是完全不同的shell语法值得一提。在 shell 脚本中,变量的名称必须以 为前缀$以扩展为变量的值。在awk. In awk,i本身扩展到它的值——在这种情况下是 3 或 4——$后面跟一个数字表示该编号位置的字段。因此$i = ""ith 字段设置为空字符串。

然后print命令,不带参数,默认打印整行。实际上,它将行的所有字段作为由 分隔并由FS任何先前命令修改的字段,并将它们全部打印出来,OFS以换行符分隔并在末尾跟随一个换行符。


一个等效的较短命令:

如果您要将其包含在脚本中,我觉得上面的命令是最干净且最容易扩展的。它非常明确地说明了它在做什么并且非常易读。另外,整个事情可以分解为一个独立的awk脚本而无需更改;使用-v-F切换到您的awk调用时无法自动完成的事情。(当然,这不是不使用它们的理由。只是需要注意的事情。)

特别是对于一次性使用,我会使用以下内容:

awk -F, -v OFS=, '{for (i = 3; i <= 4; i++) { $i = "" }; print}' inputfile
Run Code Online (Sandbox Code Playgroud)

-F开关设置的值FS。该-v开关允许您awk在命令行上设置变量的值。

在更一般的情况下,该-v开关对于将 shell 变量作为 awk 变量传入非常有用:-v myawkvar="$myshellvar"以及更改独立awk脚本的运行时行为,您-f scriptname可以使用命令行中的选项从脚本文件中提取该脚本。


Spa*_*awk 7

</path/to/in_file awk -v 'FS=,' -v 'OFS=,' '{$3=$4=""; print}'
Run Code Online (Sandbox Code Playgroud)

解释

  • </path/to/in_file: 读取文件到标准输入。
  • -v 'FS=,' -v 'OFS=,': 将文件分隔符和输出文件分隔符设置为,.
  • '{$3=$4=""; print}':将第 3 和第 4 个字段设置为空白,然后打印整行(简写形式由jasonwryan 提供)。

  • `{$3=$4=""; 打印}`也有效... (2认同)

mik*_*erv 6

sed 's/\([^,]*,\)\{2\}/,,/2' <in >out
Run Code Online (Sandbox Code Playgroud)
sed 's/\([^,]*,\)\{2\}/,,/2' <in >out
Run Code Online (Sandbox Code Playgroud)

这将用两个逗号替换第二次出现的一组两个连续的逗号分隔字段。

你也可以这样做:

sed 's/[^,]*//4;s///3' <in >out
Run Code Online (Sandbox Code Playgroud)

...它将任何 num 非逗号字符序列的第 4 次和第 3 次替换为空。

像@Wildcard 那样做 - 使用可扩展的循环:

sed -e:t -e'/\n\{2\}/!s/\(\n*\)[^,]*./\n\1/3;/\n$/!tt' -e's///;y/\n/,/'
Run Code Online (Sandbox Code Playgroud)

...或者...

sed -e:t -e's/\n$//;s/\n/&/2;to'  \
    -e's/\(\n*\)[^,]*./\1\n/3;tt' \
    -e:o -ey/\\n/,/
Run Code Online (Sandbox Code Playgroud)

...3您将开始消隐的字段编号在哪里,,是分隔符,以及2您将全部消隐的字段数。

不管你怎么写...

sed "$script" <<""
U
N,P
I,M,UNIX
X,Y,BASH,333
P,R,SCRIPT,444,E,9
Run Code Online (Sandbox Code Playgroud)
U,N,,,A,5
N,P,,,B,6
I,M,,,C,7
X,Y,,,D,8
P,R,,,E,9
Run Code Online (Sandbox Code Playgroud)

...虽然您可能需要使用文字换行符代替nin ... /\1\n/3