How to delete input field in AWK?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
7
down vote

favorite
1












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?







share|improve this question


























    up vote
    7
    down vote

    favorite
    1












    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?







    share|improve this question
























      up vote
      7
      down vote

      favorite
      1









      up vote
      7
      down vote

      favorite
      1






      1





      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?







      share|improve this question














      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?









      share|improve this question













      share|improve this question




      share|improve this question








      edited Feb 19 at 0:40









      Jeff Schaller

      31.2k846105




      31.2k846105










      asked Feb 19 at 0:14









      MLu

      1,141819




      1,141819




















          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.






          share|improve this answer





























            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





            share|improve this answer




















              Your Answer







              StackExchange.ready(function()
              var channelOptions =
              tags: "".split(" "),
              id: "106"
              ;
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function()
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled)
              StackExchange.using("snippets", function()
              createEditor();
              );

              else
              createEditor();

              );

              function createEditor()
              StackExchange.prepareEditor(
              heartbeatType: 'answer',
              convertImagesToLinks: false,
              noModals: false,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: null,
              bindNavPrevention: true,
              postfix: "",
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              );



              );








               

              draft saved


              draft discarded


















              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






























              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.






              share|improve this answer


























                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.






                share|improve this answer
























                  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.






                  share|improve this answer














                  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.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Feb 19 at 1:58

























                  answered Feb 19 at 1:43









                  cas

                  37.6k44392




                  37.6k44392






















                      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





                      share|improve this answer
























                        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





                        share|improve this answer






















                          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





                          share|improve this answer












                          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






                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Feb 19 at 5:25









                          Sundeep

                          6,9511826




                          6,9511826






















                               

                              draft saved


                              draft discarded


























                               


                              draft saved


                              draft discarded














                              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













































































                              Popular posts from this blog

                              Peggy Mitchell

                              Palaiologos

                              The Forum (Inglewood, California)