True column deletion, not selecting all columns that you want
Okay, so you can use the cut command, however it still isn't the deletion of said column, its selection of the columns you want, which does have an infinite column option. So one solution if you wanted to select the 2nd column and then every column from 4 onwards is:
cut -f 2,4- file.txt
However I am still interested to know if there's an actual deletion command?
While awk
doesn't have a function to actually delete a field from a line, you can set particular column(s) to the empty string.
However, there is a common trick which can be used to delete columns (e.g. columns 5 and 7):
awk '{$5=$7="" ; $0=$0;$1=$1}1'
The $0=$0;$1=1
sets $0 to itself and $1 to itself. This has the side-effect of removing any extra field delimiters (i.e. the delimiters that would otherwise exist immediately after the now-empty fields $5 and $7)
NOTE: this will also convert all the field separators in $0 to whatever the Output Field Separator (OFS) is currently set to (e.g. with default FS and OFS, it will convert multiple tabs and spaces between fields to a single space)
With perl
, it's much easier. It does have a function (splice()
) to delete columns from an array:
perl -lane 'BEGIN{$,=" "}; splice(@F,4,1); splice(@F,5,1); print @F'
$,=" "
sets the output field separator to a single space.
Notes:
perl arrays start from 0, not 1. so
@F[4]
is the fifth column.this deletes column 5, so the second column (7th) we want to delete is now the 6th column, which is why the second
splice
deletes@F[5]
.
To avoid any potential confusion here, delete the columns in reverse order:
perl -lane 'BEGIN{$,=" "}; splice(@F,6,1); splice(@F,4,1); print @F'
or you can use a loop:
perl -lane 'BEGIN{$,=" "}; foreach $c (7,5) {splice(@F,$c-1,1)}; print @F'
BTW, if you only want to delete the first or the last column, you can use shift @F
, or pop @F
.
Output:
with the following input:
1 2 3 4 5 6 7 8 9 10
10 9 8 7 6 5 4 3 2 1
a b c d e f h i j k
All of the above scripts will produce the following output:
1 2 3 4 6 8 9 10
10 9 8 7 5 3 2 1
a b c d f i j k
It depends on what you mean by columns. If by columns you actually mean character columns and not delimited fields, the obscure colrm allows to specify the starting column, or the starting and ending columns for a range of columns to be deleted. There is no way through to delete an arbitrary number of non-contiguous columns in one invocation