Unix 从文件头匹配的空格分隔文件中删除列
我有一个空格分隔的输入文本文件。我想使用sed或awk删除列标题为size的列 输入文件:Unix 从文件头匹配的空格分隔文件中删除列,unix,sed,awk,Unix,Sed,Awk,我有一个空格分隔的输入文本文件。我想使用sed或awk删除列标题为size的列 输入文件: id quantity colour shape size colour shape size colour shape size 1 10 blue square 10 red triangle 8 pink circle 3 2 12 yellow pentagon 3 orange rectangle 9 purple oval 6 期望输出: id quantity colour shape c
id quantity colour shape size colour shape size colour shape size
1 10 blue square 10 red triangle 8 pink circle 3
2 12 yellow pentagon 3 orange rectangle 9 purple oval 6
期望输出:
id quantity colour shape colour shape colour shape
1 10 blue square red triangle pink circle
2 12 yellow pentagon orange rectangle purple oval
给定固定的文件格式:
cut -f 1-4,6-7,9-10 infile
给定固定的文件格式:
cut -f 1-4,6-7,9-10 infile
使用
awk
的通用解决方案。开始
块中有一个硬编码变量(列_至_删除
),用于指示要删除的字段的位置。然后,脚本将计算每个字段的宽度,并删除与变量位置匹配的字段
假设infle
包含问题的内容和script.awk
的以下内容:
BEGIN {
## Hard-coded positions of fields to delete. Separate them with spaces.
columns_to_delete = "5 8 11"
## Save positions in an array to handle it better.
split( columns_to_delete, arr_columns )
}
## Process header.
FNR == 1 {
## Split header with a space followed by any non-space character.
split( $0, h, /([[:space:]])([^[:space:]])/, seps )
## Use FIELDWIDTHS to handle fixed format of data. Set that variable with
## length of each field, taking into account spaces.
for ( i = 1; i <= length( h ); i++ ) {
len = length( h[i] seps[i] )
FIELDWIDTHS = FIELDWIDTHS " " (i == 1 ? --len : i == length( h ) ? ++len : len)
}
## Re-calculate fields with new FIELDWIDTHS variable.
$0 = $0
}
## Process header too, and every line with data.
{
## Flag to know if 'p'rint to output a field.
p = 1
## Go throught all fields, if found in the array of columns to delete, reset
## the 'print' flag.
for ( i = 1; i <= NF; i++ ) {
for ( j = 1; j <= length( arr_columns ); j++ ) {
if ( i == arr_columns[j] ) {
p = 0
break
}
}
## Check 'print' flag and print if set.
if ( p ) {
printf "%s", $i
}
else {
printf " "
}
p = 1
}
printf "\n"
}
具有以下输出:
id quantity colour shape colour shape colour shape
1 10 blue square red triangle pink circle
2 12 yellow pentagon orange rectangle purple oval
编辑:哦,刚才意识到输出不正确,因为两个字段之间存在连接。修复这将是太多的工作,因为在开始处理任何内容之前,需要检查每行的最大列大小。但通过这个剧本,我希望你能理解。现在没时间,也许我可以稍后再修,但不确定 编辑2:修复了为删除的每个字段添加额外空间的问题。这比预期的容易:-)
编辑3:参见注释 我修改了
BEGIN
块,以检查是否提供了一个额外的变量作为参数
BEGIN {
## Check if a variable 'delete_col' has been provided as argument.
if ( ! delete_col ) {
printf "%s\n", "Usage: awk -v delete_col=\"column_name\" -f script.awk " ARGV[1]
exit 0
}
}
并将计算要删除的列数的过程添加到FNR==1
模式中:
## Process header.
FNR == 1 {
## Find column position to delete given the name provided as argument.
for ( i = 1; i <= NF; i++ ) {
if ( $i == delete_col ) {
columns_to_delete = columns_to_delete " " i
}
}
## Save positions in an array to handle it better.
split( columns_to_delete, arr_columns )
## ...
## No modifications from here until the end. Same code as in the original script.
## ...
}
结果将是相同的。使用
awk
的通用解决方案。开始
块中有一个硬编码变量(列_至_删除
),用于指示要删除的字段的位置。然后,脚本将计算每个字段的宽度,并删除与变量位置匹配的字段
假设infle
包含问题的内容和script.awk
的以下内容:
BEGIN {
## Hard-coded positions of fields to delete. Separate them with spaces.
columns_to_delete = "5 8 11"
## Save positions in an array to handle it better.
split( columns_to_delete, arr_columns )
}
## Process header.
FNR == 1 {
## Split header with a space followed by any non-space character.
split( $0, h, /([[:space:]])([^[:space:]])/, seps )
## Use FIELDWIDTHS to handle fixed format of data. Set that variable with
## length of each field, taking into account spaces.
for ( i = 1; i <= length( h ); i++ ) {
len = length( h[i] seps[i] )
FIELDWIDTHS = FIELDWIDTHS " " (i == 1 ? --len : i == length( h ) ? ++len : len)
}
## Re-calculate fields with new FIELDWIDTHS variable.
$0 = $0
}
## Process header too, and every line with data.
{
## Flag to know if 'p'rint to output a field.
p = 1
## Go throught all fields, if found in the array of columns to delete, reset
## the 'print' flag.
for ( i = 1; i <= NF; i++ ) {
for ( j = 1; j <= length( arr_columns ); j++ ) {
if ( i == arr_columns[j] ) {
p = 0
break
}
}
## Check 'print' flag and print if set.
if ( p ) {
printf "%s", $i
}
else {
printf " "
}
p = 1
}
printf "\n"
}
具有以下输出:
id quantity colour shape colour shape colour shape
1 10 blue square red triangle pink circle
2 12 yellow pentagon orange rectangle purple oval
编辑:哦,刚才意识到输出不正确,因为两个字段之间存在连接。修复这将是太多的工作,因为在开始处理任何内容之前,需要检查每行的最大列大小。但通过这个剧本,我希望你能理解。现在没时间,也许我可以稍后再修,但不确定 编辑2:修复了为删除的每个字段添加额外空间的问题。这比预期的容易:-)
编辑3:参见注释 我修改了
BEGIN
块,以检查是否提供了一个额外的变量作为参数
BEGIN {
## Check if a variable 'delete_col' has been provided as argument.
if ( ! delete_col ) {
printf "%s\n", "Usage: awk -v delete_col=\"column_name\" -f script.awk " ARGV[1]
exit 0
}
}
并将计算要删除的列数的过程添加到FNR==1
模式中:
## Process header.
FNR == 1 {
## Find column position to delete given the name provided as argument.
for ( i = 1; i <= NF; i++ ) {
if ( $i == delete_col ) {
columns_to_delete = columns_to_delete " " i
}
}
## Save positions in an array to handle it better.
split( columns_to_delete, arr_columns )
## ...
## No modifications from here until the end. Same code as in the original script.
## ...
}
结果将是相同的。使用:
$cut-d'-f1-4,6,7,9,10
使用:
$cut-d'-f1-4,6,7,9,10
awk
命令
结果
awk
命令
结果
如果您有GNU cut可用,可以这样做:
columns=$(head-n1输入文件\
|tr“”\n'\
|n类\
|grep大小\
|tr-s“\
|切割-f1\
|tr-d“\
|粘贴-sd“,”)
cut--补足-d'-f$列输入文件
它根据标题生成一个逗号分隔的列表,然后从输入文件中剪切该列表的补码。如果您有GNU cut可用,可以这样做:
columns=$(head-n1输入文件\
|tr“”\n'\
|n类\
|grep大小\
|tr-s“\
|切割-f1\
|tr-d“\
|粘贴-sd“,”)
cut--补足-d'-f$列输入文件
根据标题生成逗号分隔的列表,然后从输入文件中剪切该列表的补码。文件格式不固定,因此希望在有标题匹配的地方删除文件格式不固定,因此希望在有标题匹配的地方删除。是否有任何方法可以在不硬编码列号(使用列标题名)的情况下执行此操作?@SantoshPillai:哪个分隔符?我的意思是输出没有任何分隔符/分隔符(列之间没有空格)@SantoshPillai:首先,前面注释的示例文件似乎与您在问题中粘贴的文件不同。它有不同的格式,或者说很清楚,根本没有格式,只有空格。我认为
awk
可以做比这个脚本更简单的工作。第二,我运行了一个测试,输出文件中的字段也是用空格分隔的,我不知道你们的意思。给我们一个好的(简短的)输入文件示例,并向我们展示该脚本失败的情况。对我和其他用户来说,帮助您会更容易。我很抱歉。在我的问题中,我为输入数据添加了额外的空格,以使其可读(我现在已经删除了这个)。脚本成功删除了大小列,但也删除了其他连续数据列之间的空格。我得到了输出idquantitycolourshape colorShape colorShape 110bluesquare redtriangle pinkcircle 212YellowPentagan orangerectangle purpleovalIs有没有方法不用硬编码列号(使用列标题名)?@SantoshPillai:哪个分隔符?我的意思是输出没有任何分隔符/分隔符(两栏之间没有空格)@SantoshPillai:首先,前面评论的示例文件似乎与您在问题中粘贴的文件不同,它有不同的格式,或者说很清楚,根本没有格式,
id quantity colour shape colour shape colour shape
1 10 blue square red triangle pink circle
2 12 yellow pentagon orange rectangle purple oval