How to delete input field in AWK?

Clash Royale CLAN TAG#URR8PPP
up vote
7
down vote
favorite
I'm transforming some data with awk (or gawk) and want to delete one of the input fields before printing the output again.
What I want to achieve is this:
~ $ echo 'field1,field2,field3' | awk -F, 'transform($1); delete($2); print $0;'
new_field1,field3
I can't just assign an empty string to $2 because that leads to new_field1,,field3 (note the two commas).
I could explicitly print only the fields that I want but that's not very elegant because I've got far more field than 3 and also there are optional fields at the end (not shown here). That's why I prefer print $0. Just need to get rid of some fields first.
Any idea?
awk
add a comment |Â
up vote
7
down vote
favorite
I'm transforming some data with awk (or gawk) and want to delete one of the input fields before printing the output again.
What I want to achieve is this:
~ $ echo 'field1,field2,field3' | awk -F, 'transform($1); delete($2); print $0;'
new_field1,field3
I can't just assign an empty string to $2 because that leads to new_field1,,field3 (note the two commas).
I could explicitly print only the fields that I want but that's not very elegant because I've got far more field than 3 and also there are optional fields at the end (not shown here). That's why I prefer print $0. Just need to get rid of some fields first.
Any idea?
awk
add a comment |Â
up vote
7
down vote
favorite
up vote
7
down vote
favorite
I'm transforming some data with awk (or gawk) and want to delete one of the input fields before printing the output again.
What I want to achieve is this:
~ $ echo 'field1,field2,field3' | awk -F, 'transform($1); delete($2); print $0;'
new_field1,field3
I can't just assign an empty string to $2 because that leads to new_field1,,field3 (note the two commas).
I could explicitly print only the fields that I want but that's not very elegant because I've got far more field than 3 and also there are optional fields at the end (not shown here). That's why I prefer print $0. Just need to get rid of some fields first.
Any idea?
awk
I'm transforming some data with awk (or gawk) and want to delete one of the input fields before printing the output again.
What I want to achieve is this:
~ $ echo 'field1,field2,field3' | awk -F, 'transform($1); delete($2); print $0;'
new_field1,field3
I can't just assign an empty string to $2 because that leads to new_field1,,field3 (note the two commas).
I could explicitly print only the fields that I want but that's not very elegant because I've got far more field than 3 and also there are optional fields at the end (not shown here). That's why I prefer print $0. Just need to get rid of some fields first.
Any idea?
awk
edited Feb 19 at 0:40
Jeff Schaller
31.2k846105
31.2k846105
asked Feb 19 at 0:14
MLu
1,141819
1,141819
add a comment |Â
add a comment |Â
2 Answers
2
active
oldest
votes
up vote
7
down vote
accepted
Deleting fields in awk is notoriously difficult. It seems to be such a simple (and often required) operation but it's harder than it should be.
See Is there a way to completely delete fields in awk, so that extra delimiters do not print?
from Stack Overflow for a good way to do this.
I've copied the rmcol() function in @ghoti's answer, so that we have a copy here on U&L:
function rmcol(col, i)
for (i=col; i<NF; i++)
$i=$(i+1)
NF--
It deletes the specified column from the current input line and decrements the field counter (NF) to match.
I have no idea what your transform() function does, so I won't even attempt to duplicate that - but here's an example of using rmcol() in an awk one-liner:
$ echo 'field1,field2,field3' | awk -F, -v OFS=, '
function rmcol(col, i)
for (i=col; i<NF; i++)
$i=$(i+1)
NF--
rmcol(2); print;
'
field1,field3
BTW, if you need to delete multiple fields from an input line, it is best/easiest to delete them in reverse order. That is, delete the highest-numbered fields first. Why? Because the higher-numbered fields will be renumbered every time you delete a lower-numbered field, making it very difficult to keep track of which field number belongs to which field.
BTW, delete() in awk is for deleting elements of an array - not for deleting fields from an input line. You could split() each input line (on FS) into an array and delete the 2nd array element, but then you'd have to write a join() function to print the array with a comma (or OFS) separating each field.
Even doing that would be more complicated than one would expect because all arrays in awk are associative arrays (i.e. they're not numerically indexed) - so delete(array[2]) won't automatically shift array elements 3+ into elements 2+. You'd have to write your own wrapper function around delete() to do pretty much the same thing for arrays that rmcol() does for input fields.
add a comment |Â
up vote
4
down vote
Some alternatives
1) pre-process the input to remove the field first, easy to do with cut if field separator is single character
$ s='field1,field2,field3'
$ # use 'cut -d, -f1,3-' if --complement option is not available
$ echo "$s" | cut -d, --complement -f2
field1,field3
$ echo "$s" | cut -d, --complement -f2 | awk 'BEGINFS=OFS="," $1="new" 1'
new,field3
2) use perl
$ # indexing starts from 0, the array @F contains the input fields
$ # $#F will give index of last element in the array
$ echo "$s" | perl -F, -lane '$F[0]="new"; print join ",", @F[0,2..$#F]'
new,field3
add a comment |Â
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
7
down vote
accepted
Deleting fields in awk is notoriously difficult. It seems to be such a simple (and often required) operation but it's harder than it should be.
See Is there a way to completely delete fields in awk, so that extra delimiters do not print?
from Stack Overflow for a good way to do this.
I've copied the rmcol() function in @ghoti's answer, so that we have a copy here on U&L:
function rmcol(col, i)
for (i=col; i<NF; i++)
$i=$(i+1)
NF--
It deletes the specified column from the current input line and decrements the field counter (NF) to match.
I have no idea what your transform() function does, so I won't even attempt to duplicate that - but here's an example of using rmcol() in an awk one-liner:
$ echo 'field1,field2,field3' | awk -F, -v OFS=, '
function rmcol(col, i)
for (i=col; i<NF; i++)
$i=$(i+1)
NF--
rmcol(2); print;
'
field1,field3
BTW, if you need to delete multiple fields from an input line, it is best/easiest to delete them in reverse order. That is, delete the highest-numbered fields first. Why? Because the higher-numbered fields will be renumbered every time you delete a lower-numbered field, making it very difficult to keep track of which field number belongs to which field.
BTW, delete() in awk is for deleting elements of an array - not for deleting fields from an input line. You could split() each input line (on FS) into an array and delete the 2nd array element, but then you'd have to write a join() function to print the array with a comma (or OFS) separating each field.
Even doing that would be more complicated than one would expect because all arrays in awk are associative arrays (i.e. they're not numerically indexed) - so delete(array[2]) won't automatically shift array elements 3+ into elements 2+. You'd have to write your own wrapper function around delete() to do pretty much the same thing for arrays that rmcol() does for input fields.
add a comment |Â
up vote
7
down vote
accepted
Deleting fields in awk is notoriously difficult. It seems to be such a simple (and often required) operation but it's harder than it should be.
See Is there a way to completely delete fields in awk, so that extra delimiters do not print?
from Stack Overflow for a good way to do this.
I've copied the rmcol() function in @ghoti's answer, so that we have a copy here on U&L:
function rmcol(col, i)
for (i=col; i<NF; i++)
$i=$(i+1)
NF--
It deletes the specified column from the current input line and decrements the field counter (NF) to match.
I have no idea what your transform() function does, so I won't even attempt to duplicate that - but here's an example of using rmcol() in an awk one-liner:
$ echo 'field1,field2,field3' | awk -F, -v OFS=, '
function rmcol(col, i)
for (i=col; i<NF; i++)
$i=$(i+1)
NF--
rmcol(2); print;
'
field1,field3
BTW, if you need to delete multiple fields from an input line, it is best/easiest to delete them in reverse order. That is, delete the highest-numbered fields first. Why? Because the higher-numbered fields will be renumbered every time you delete a lower-numbered field, making it very difficult to keep track of which field number belongs to which field.
BTW, delete() in awk is for deleting elements of an array - not for deleting fields from an input line. You could split() each input line (on FS) into an array and delete the 2nd array element, but then you'd have to write a join() function to print the array with a comma (or OFS) separating each field.
Even doing that would be more complicated than one would expect because all arrays in awk are associative arrays (i.e. they're not numerically indexed) - so delete(array[2]) won't automatically shift array elements 3+ into elements 2+. You'd have to write your own wrapper function around delete() to do pretty much the same thing for arrays that rmcol() does for input fields.
add a comment |Â
up vote
7
down vote
accepted
up vote
7
down vote
accepted
Deleting fields in awk is notoriously difficult. It seems to be such a simple (and often required) operation but it's harder than it should be.
See Is there a way to completely delete fields in awk, so that extra delimiters do not print?
from Stack Overflow for a good way to do this.
I've copied the rmcol() function in @ghoti's answer, so that we have a copy here on U&L:
function rmcol(col, i)
for (i=col; i<NF; i++)
$i=$(i+1)
NF--
It deletes the specified column from the current input line and decrements the field counter (NF) to match.
I have no idea what your transform() function does, so I won't even attempt to duplicate that - but here's an example of using rmcol() in an awk one-liner:
$ echo 'field1,field2,field3' | awk -F, -v OFS=, '
function rmcol(col, i)
for (i=col; i<NF; i++)
$i=$(i+1)
NF--
rmcol(2); print;
'
field1,field3
BTW, if you need to delete multiple fields from an input line, it is best/easiest to delete them in reverse order. That is, delete the highest-numbered fields first. Why? Because the higher-numbered fields will be renumbered every time you delete a lower-numbered field, making it very difficult to keep track of which field number belongs to which field.
BTW, delete() in awk is for deleting elements of an array - not for deleting fields from an input line. You could split() each input line (on FS) into an array and delete the 2nd array element, but then you'd have to write a join() function to print the array with a comma (or OFS) separating each field.
Even doing that would be more complicated than one would expect because all arrays in awk are associative arrays (i.e. they're not numerically indexed) - so delete(array[2]) won't automatically shift array elements 3+ into elements 2+. You'd have to write your own wrapper function around delete() to do pretty much the same thing for arrays that rmcol() does for input fields.
Deleting fields in awk is notoriously difficult. It seems to be such a simple (and often required) operation but it's harder than it should be.
See Is there a way to completely delete fields in awk, so that extra delimiters do not print?
from Stack Overflow for a good way to do this.
I've copied the rmcol() function in @ghoti's answer, so that we have a copy here on U&L:
function rmcol(col, i)
for (i=col; i<NF; i++)
$i=$(i+1)
NF--
It deletes the specified column from the current input line and decrements the field counter (NF) to match.
I have no idea what your transform() function does, so I won't even attempt to duplicate that - but here's an example of using rmcol() in an awk one-liner:
$ echo 'field1,field2,field3' | awk -F, -v OFS=, '
function rmcol(col, i)
for (i=col; i<NF; i++)
$i=$(i+1)
NF--
rmcol(2); print;
'
field1,field3
BTW, if you need to delete multiple fields from an input line, it is best/easiest to delete them in reverse order. That is, delete the highest-numbered fields first. Why? Because the higher-numbered fields will be renumbered every time you delete a lower-numbered field, making it very difficult to keep track of which field number belongs to which field.
BTW, delete() in awk is for deleting elements of an array - not for deleting fields from an input line. You could split() each input line (on FS) into an array and delete the 2nd array element, but then you'd have to write a join() function to print the array with a comma (or OFS) separating each field.
Even doing that would be more complicated than one would expect because all arrays in awk are associative arrays (i.e. they're not numerically indexed) - so delete(array[2]) won't automatically shift array elements 3+ into elements 2+. You'd have to write your own wrapper function around delete() to do pretty much the same thing for arrays that rmcol() does for input fields.
edited Feb 19 at 1:58
answered Feb 19 at 1:43
cas
37.6k44392
37.6k44392
add a comment |Â
add a comment |Â
up vote
4
down vote
Some alternatives
1) pre-process the input to remove the field first, easy to do with cut if field separator is single character
$ s='field1,field2,field3'
$ # use 'cut -d, -f1,3-' if --complement option is not available
$ echo "$s" | cut -d, --complement -f2
field1,field3
$ echo "$s" | cut -d, --complement -f2 | awk 'BEGINFS=OFS="," $1="new" 1'
new,field3
2) use perl
$ # indexing starts from 0, the array @F contains the input fields
$ # $#F will give index of last element in the array
$ echo "$s" | perl -F, -lane '$F[0]="new"; print join ",", @F[0,2..$#F]'
new,field3
add a comment |Â
up vote
4
down vote
Some alternatives
1) pre-process the input to remove the field first, easy to do with cut if field separator is single character
$ s='field1,field2,field3'
$ # use 'cut -d, -f1,3-' if --complement option is not available
$ echo "$s" | cut -d, --complement -f2
field1,field3
$ echo "$s" | cut -d, --complement -f2 | awk 'BEGINFS=OFS="," $1="new" 1'
new,field3
2) use perl
$ # indexing starts from 0, the array @F contains the input fields
$ # $#F will give index of last element in the array
$ echo "$s" | perl -F, -lane '$F[0]="new"; print join ",", @F[0,2..$#F]'
new,field3
add a comment |Â
up vote
4
down vote
up vote
4
down vote
Some alternatives
1) pre-process the input to remove the field first, easy to do with cut if field separator is single character
$ s='field1,field2,field3'
$ # use 'cut -d, -f1,3-' if --complement option is not available
$ echo "$s" | cut -d, --complement -f2
field1,field3
$ echo "$s" | cut -d, --complement -f2 | awk 'BEGINFS=OFS="," $1="new" 1'
new,field3
2) use perl
$ # indexing starts from 0, the array @F contains the input fields
$ # $#F will give index of last element in the array
$ echo "$s" | perl -F, -lane '$F[0]="new"; print join ",", @F[0,2..$#F]'
new,field3
Some alternatives
1) pre-process the input to remove the field first, easy to do with cut if field separator is single character
$ s='field1,field2,field3'
$ # use 'cut -d, -f1,3-' if --complement option is not available
$ echo "$s" | cut -d, --complement -f2
field1,field3
$ echo "$s" | cut -d, --complement -f2 | awk 'BEGINFS=OFS="," $1="new" 1'
new,field3
2) use perl
$ # indexing starts from 0, the array @F contains the input fields
$ # $#F will give index of last element in the array
$ echo "$s" | perl -F, -lane '$F[0]="new"; print join ",", @F[0,2..$#F]'
new,field3
answered Feb 19 at 5:25
Sundeep
6,9511826
6,9511826
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f425044%2fhow-to-delete-input-field-in-awk%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password