Delete nth line (when counted from the bottom) Announcing the arrival of Valued Associate #679: Cesar Manara Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern) 2019 Community Moderator Election Results Why I closed the “Why is Kali so hard” questionhow to delete line from the XML fileHow to remove line based on Delimeter in perl / Shell?Replace multiple lines with a string when the line numbers are stored in a fileawk + count field separator in csv and print line numberUsing sed to delete a whole line if it contains only specific numberDelete multi-line stringsDelete text between parentheses, but never past empty lineDelete certain character from the next line at the same position(s)?Remove multiple strings from file on command line, high performancehow to remove the empty/blank lines from files that appears as @ from vi

What do you call the main part of a joke?

Amount of permutations on an NxNxN Rubik's Cube

Semigroups with no morphisms between them

macOS: Name for app shortcut screen found by pinching with thumb and three fingers

How does the math work when buying airline miles?

Do wooden building fires get hotter than 600°C?

What's the difference between the capability remove_users and delete_users?

What initially awakened the Balrog?

Drawing spherical mirrors

Sum letters are not two different

What's the point of the test set?

Why are vacuum tubes still used in amateur radios?

How were pictures turned from film to a big picture in a picture frame before digital scanning?

Is multiple magic items in one inherently imbalanced?

What is the chair depicted in Cesare Maccari's 1889 painting "Cicerone denuncia Catilina"?

How could we fake a moon landing now?

What to do with repeated rejections for phd position

Random body shuffle every night—can we still function?

What are the discoveries that have been possible with the rejection of positivism?

One-one communication

Has negative voting ever been officially implemented in elections, or seriously proposed, or even studied?

Do I really need to have a message in a novel to appeal to readers?

Why are my pictures showing a dark band on one edge?

Google .dev domain strangely redirects to https



Delete nth line (when counted from the bottom)



Announcing the arrival of Valued Associate #679: Cesar Manara
Planned maintenance scheduled April 23, 2019 at 23:30 UTC (7:30pm US/Eastern)
2019 Community Moderator Election Results
Why I closed the “Why is Kali so hard” questionhow to delete line from the XML fileHow to remove line based on Delimeter in perl / Shell?Replace multiple lines with a string when the line numbers are stored in a fileawk + count field separator in csv and print line numberUsing sed to delete a whole line if it contains only specific numberDelete multi-line stringsDelete text between parentheses, but never past empty lineDelete certain character from the next line at the same position(s)?Remove multiple strings from file on command line, high performancehow to remove the empty/blank lines from files that appears as @ from vi



.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;








5















There are unknown number of lines in a file. How to delete nth line (when counted from the bottom) with one-liner command (you may use more than one if it is necessary) on Unix platform.










share|improve this question









New contributor




Swapnil Dhule is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.


























    5















    There are unknown number of lines in a file. How to delete nth line (when counted from the bottom) with one-liner command (you may use more than one if it is necessary) on Unix platform.










    share|improve this question









    New contributor




    Swapnil Dhule is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.






















      5












      5








      5








      There are unknown number of lines in a file. How to delete nth line (when counted from the bottom) with one-liner command (you may use more than one if it is necessary) on Unix platform.










      share|improve this question









      New contributor




      Swapnil Dhule is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.












      There are unknown number of lines in a file. How to delete nth line (when counted from the bottom) with one-liner command (you may use more than one if it is necessary) on Unix platform.







      awk sed perl






      share|improve this question









      New contributor




      Swapnil Dhule is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      Swapnil Dhule is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited yesterday







      Swapnil Dhule













      New contributor




      Swapnil Dhule is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 2 days ago









      Swapnil DhuleSwapnil Dhule

      263




      263




      New contributor




      Swapnil Dhule is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Swapnil Dhule is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Swapnil Dhule is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.




















          8 Answers
          8






          active

          oldest

          votes


















          13














          To remove for example the 4th line from the bottom using sed:



          tac input | sed '4d' | tac


          To overwrite the input file:



          tmpfile=$(mktemp)
          tac input | sed '4d' | tac > "$tmpfile" && mv "$tmpfile" input





          share|improve this answer

























          • Thanks Panki! However this won't delete line from the file. We need permanent change in file.

            – Swapnil Dhule
            2 days ago






          • 2





            Use output redirection to write to a new file, then replace the original one.

            – Panki
            2 days ago


















          3














          Pure sed:




          • If n is 1:



            sed '$ d'


            This is simple: if it's the last line, delete the pattern space, so it's not printed.




          • If n is greater than 1 (and available as $n):



            sed "
            : start
            1,$((n-1)) N; b start
            $ t end; s/^//; D
            N
            P
            D
            : end
            "


            Note $((n-1)) is expanded by the shell before sed starts.



            This fragment



            : start
            1,$((n-1)) N; b start


            stores n-1 lines in the pattern space. If sed reaches the end of the input stream during this loop, the pattern space will be printed automatically (there is no n-th line from the end, no line will be deleted).



            Suppose there is more input. Then, before we get to the last line, this fragment is iterated:



            N # read the next line of input and append it to the pattern space
            P # print the first line from the pattern space
            D # delete the first line from the pattern space and start a new cycle


            This way the pattern space is our buffer which makes the output several lines "late" according to the input. N from this fragment is able to read the last line of the input as well.



            After the last line is read, this gets executed:



            $ t end; s/^//; D 


            When this code is executed for the first time, t doesn't branch to end because there was no successful substitution before. Such no-op substitution s/^// is then performed and the first line from the pattern space is deleted (D) without being printed. This is exactly the line you want to be deleted. Since D starts a new cycle, the same line of code will eventually be executed again. This time t will branch to end.



            When sed reaches the end of the script, the pattern space is printed automatically. This way all remaining lines get printed.



            The command will generate the same output for n=2 (valid) and n=1 (invalid). I tried to find a single solution that works regardless of n. I failed, hence the special case when your n is 1.







          share|improve this answer






























            2














            This is tagged with sed and awk but the question doesn't mention these as being required for the solution. Here's a Perl filter which removes the 4th-from-last line and prints the result. The output can written to a tmp file and then used to replace the original.



             perl -e '@L = <STDIN>; splice(@L,-4,1); print @L' ./lines.txt





            share|improve this answer
































              2














              if $n hold number of line to delete



              to delete a single line use



              printf "$-%d+1,$-%d+1dnwqn" $n $n| ed -s file


              to delete n last lines



              printf "$-%d,$dnwqn" $n | ed -s file


              where




              • $%d,$d tell ed to delete n last lines (printf will insert n)


              • wq write and quit

              • -s in ed -s will keep ed silent.


              • note that no provision is made to check you have enough line to delete.


              sadly range from end can't be specified in sed ...






              share|improve this answer

























              • What do you mean you can't specify ranges with sed? sed '2,4d' works fine on my end..

                – Panki
                2 days ago











              • I like to add -s to the call to ed; quiets the output a bit.

                – Jeff Schaller
                2 days ago











              • @JeffSchaller done

                – Archemar
                2 days ago


















              1














              Neither standard sed nor awk support editing in place.



              For that, you better use ed(1) or ex(1):



              printf '$-%ddnwn' 1 | ed -s your_file


              Or with here-doc



              ed -s <<'EOT' your_file
              $-1d
              w
              EOT


              With advanced shells like bash, zsh orksh93 you can use the $'...' syntax and here-strings:



              ed -s <<<$'$-1dnw' your_file 


              Notice that the $ address means the last line from the file; so the index 1 there is 0-based; for the 1st line from the end replace the 1 with 0 ($-0), for the 3nd with 2 ($-2), etc.



              Putting it in a function:



              del_nth_line_from_end() ed -s "$1"; 


              Instead of ed -s you can use ex -s or vim -es everywhere.






              share|improve this answer
































                0














                sed cannot calculate nth row from bottom by itself, so we need to that before, e.g. using awk:



                Delete 4th row from bottom:



                delrow=$(awk -v n=4 'END print NR-n+1 ' file)
                sed -i "$delrowd" file





                share|improve this answer






























                  0














                  An one-line, in-place solution:



                  With gawk, this will delete the 42nd line from the bottom:



                  gawk -i inplace 'i==0 if(FNR>t)t=FNRelsei=1 i==1 && FNR!=t-42 print' input input


                  The 42 can be replaced with any number. If 0 is used then the last line is deleted.



                  Notice that the input file is specified twice. This forces two iterations of the file with gawk. In the first iteration (i==0) the total number of lines (t) is established. In the second iteration, the nth line from the end is not output.



                  The file is modified in place by using the -i option.






                  share|improve this answer






























                    0














                    You can combine head and tail to achieve this.



                    If the nth line from the bottom needs to be deleted




                    1. head reads from standard input and reports to standard output total -n lines from the top


                    2. tail reads and reports to standard output the bottom n-1 lines from standard input.

                    3. Taken as a whole, the lines are thus reported to standard output in order, with the *nth` line from the end being skipped

                    This solution depends on head leaving the file offset of the open file description just after the last reported line - I believe GNU head does indeed do this when standard input is redirected from a file



                    n=200; tmpfile=$(mktemp) && head -n -$n; tail -n -$((n-1)); <file >"$tmpfile" 
                    && mv -- "$tmpfile" file





                    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',
                      autoActivateHeartbeat: false,
                      convertImagesToLinks: false,
                      noModals: true,
                      showLowRepImageUploadWarning: true,
                      reputationToPostImages: null,
                      bindNavPrevention: true,
                      postfix: "",
                      imageUploader:
                      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                      allowUrls: true
                      ,
                      onDemand: true,
                      discardSelector: ".discard-answer"
                      ,immediatelyShowMarkdownHelp:true
                      );



                      );






                      Swapnil Dhule is a new contributor. Be nice, and check out our Code of Conduct.









                      draft saved

                      draft discarded


















                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f512947%2fdelete-nth-line-when-counted-from-the-bottom%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown

























                      8 Answers
                      8






                      active

                      oldest

                      votes








                      8 Answers
                      8






                      active

                      oldest

                      votes









                      active

                      oldest

                      votes






                      active

                      oldest

                      votes









                      13














                      To remove for example the 4th line from the bottom using sed:



                      tac input | sed '4d' | tac


                      To overwrite the input file:



                      tmpfile=$(mktemp)
                      tac input | sed '4d' | tac > "$tmpfile" && mv "$tmpfile" input





                      share|improve this answer

























                      • Thanks Panki! However this won't delete line from the file. We need permanent change in file.

                        – Swapnil Dhule
                        2 days ago






                      • 2





                        Use output redirection to write to a new file, then replace the original one.

                        – Panki
                        2 days ago















                      13














                      To remove for example the 4th line from the bottom using sed:



                      tac input | sed '4d' | tac


                      To overwrite the input file:



                      tmpfile=$(mktemp)
                      tac input | sed '4d' | tac > "$tmpfile" && mv "$tmpfile" input





                      share|improve this answer

























                      • Thanks Panki! However this won't delete line from the file. We need permanent change in file.

                        – Swapnil Dhule
                        2 days ago






                      • 2





                        Use output redirection to write to a new file, then replace the original one.

                        – Panki
                        2 days ago













                      13












                      13








                      13







                      To remove for example the 4th line from the bottom using sed:



                      tac input | sed '4d' | tac


                      To overwrite the input file:



                      tmpfile=$(mktemp)
                      tac input | sed '4d' | tac > "$tmpfile" && mv "$tmpfile" input





                      share|improve this answer















                      To remove for example the 4th line from the bottom using sed:



                      tac input | sed '4d' | tac


                      To overwrite the input file:



                      tmpfile=$(mktemp)
                      tac input | sed '4d' | tac > "$tmpfile" && mv "$tmpfile" input






                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited 2 days ago









                      glenn jackman

                      53.2k573114




                      53.2k573114










                      answered 2 days ago









                      PankiPanki

                      1,030514




                      1,030514












                      • Thanks Panki! However this won't delete line from the file. We need permanent change in file.

                        – Swapnil Dhule
                        2 days ago






                      • 2





                        Use output redirection to write to a new file, then replace the original one.

                        – Panki
                        2 days ago

















                      • Thanks Panki! However this won't delete line from the file. We need permanent change in file.

                        – Swapnil Dhule
                        2 days ago






                      • 2





                        Use output redirection to write to a new file, then replace the original one.

                        – Panki
                        2 days ago
















                      Thanks Panki! However this won't delete line from the file. We need permanent change in file.

                      – Swapnil Dhule
                      2 days ago





                      Thanks Panki! However this won't delete line from the file. We need permanent change in file.

                      – Swapnil Dhule
                      2 days ago




                      2




                      2





                      Use output redirection to write to a new file, then replace the original one.

                      – Panki
                      2 days ago





                      Use output redirection to write to a new file, then replace the original one.

                      – Panki
                      2 days ago













                      3














                      Pure sed:




                      • If n is 1:



                        sed '$ d'


                        This is simple: if it's the last line, delete the pattern space, so it's not printed.




                      • If n is greater than 1 (and available as $n):



                        sed "
                        : start
                        1,$((n-1)) N; b start
                        $ t end; s/^//; D
                        N
                        P
                        D
                        : end
                        "


                        Note $((n-1)) is expanded by the shell before sed starts.



                        This fragment



                        : start
                        1,$((n-1)) N; b start


                        stores n-1 lines in the pattern space. If sed reaches the end of the input stream during this loop, the pattern space will be printed automatically (there is no n-th line from the end, no line will be deleted).



                        Suppose there is more input. Then, before we get to the last line, this fragment is iterated:



                        N # read the next line of input and append it to the pattern space
                        P # print the first line from the pattern space
                        D # delete the first line from the pattern space and start a new cycle


                        This way the pattern space is our buffer which makes the output several lines "late" according to the input. N from this fragment is able to read the last line of the input as well.



                        After the last line is read, this gets executed:



                        $ t end; s/^//; D 


                        When this code is executed for the first time, t doesn't branch to end because there was no successful substitution before. Such no-op substitution s/^// is then performed and the first line from the pattern space is deleted (D) without being printed. This is exactly the line you want to be deleted. Since D starts a new cycle, the same line of code will eventually be executed again. This time t will branch to end.



                        When sed reaches the end of the script, the pattern space is printed automatically. This way all remaining lines get printed.



                        The command will generate the same output for n=2 (valid) and n=1 (invalid). I tried to find a single solution that works regardless of n. I failed, hence the special case when your n is 1.







                      share|improve this answer



























                        3














                        Pure sed:




                        • If n is 1:



                          sed '$ d'


                          This is simple: if it's the last line, delete the pattern space, so it's not printed.




                        • If n is greater than 1 (and available as $n):



                          sed "
                          : start
                          1,$((n-1)) N; b start
                          $ t end; s/^//; D
                          N
                          P
                          D
                          : end
                          "


                          Note $((n-1)) is expanded by the shell before sed starts.



                          This fragment



                          : start
                          1,$((n-1)) N; b start


                          stores n-1 lines in the pattern space. If sed reaches the end of the input stream during this loop, the pattern space will be printed automatically (there is no n-th line from the end, no line will be deleted).



                          Suppose there is more input. Then, before we get to the last line, this fragment is iterated:



                          N # read the next line of input and append it to the pattern space
                          P # print the first line from the pattern space
                          D # delete the first line from the pattern space and start a new cycle


                          This way the pattern space is our buffer which makes the output several lines "late" according to the input. N from this fragment is able to read the last line of the input as well.



                          After the last line is read, this gets executed:



                          $ t end; s/^//; D 


                          When this code is executed for the first time, t doesn't branch to end because there was no successful substitution before. Such no-op substitution s/^// is then performed and the first line from the pattern space is deleted (D) without being printed. This is exactly the line you want to be deleted. Since D starts a new cycle, the same line of code will eventually be executed again. This time t will branch to end.



                          When sed reaches the end of the script, the pattern space is printed automatically. This way all remaining lines get printed.



                          The command will generate the same output for n=2 (valid) and n=1 (invalid). I tried to find a single solution that works regardless of n. I failed, hence the special case when your n is 1.







                        share|improve this answer

























                          3












                          3








                          3







                          Pure sed:




                          • If n is 1:



                            sed '$ d'


                            This is simple: if it's the last line, delete the pattern space, so it's not printed.




                          • If n is greater than 1 (and available as $n):



                            sed "
                            : start
                            1,$((n-1)) N; b start
                            $ t end; s/^//; D
                            N
                            P
                            D
                            : end
                            "


                            Note $((n-1)) is expanded by the shell before sed starts.



                            This fragment



                            : start
                            1,$((n-1)) N; b start


                            stores n-1 lines in the pattern space. If sed reaches the end of the input stream during this loop, the pattern space will be printed automatically (there is no n-th line from the end, no line will be deleted).



                            Suppose there is more input. Then, before we get to the last line, this fragment is iterated:



                            N # read the next line of input and append it to the pattern space
                            P # print the first line from the pattern space
                            D # delete the first line from the pattern space and start a new cycle


                            This way the pattern space is our buffer which makes the output several lines "late" according to the input. N from this fragment is able to read the last line of the input as well.



                            After the last line is read, this gets executed:



                            $ t end; s/^//; D 


                            When this code is executed for the first time, t doesn't branch to end because there was no successful substitution before. Such no-op substitution s/^// is then performed and the first line from the pattern space is deleted (D) without being printed. This is exactly the line you want to be deleted. Since D starts a new cycle, the same line of code will eventually be executed again. This time t will branch to end.



                            When sed reaches the end of the script, the pattern space is printed automatically. This way all remaining lines get printed.



                            The command will generate the same output for n=2 (valid) and n=1 (invalid). I tried to find a single solution that works regardless of n. I failed, hence the special case when your n is 1.







                          share|improve this answer













                          Pure sed:




                          • If n is 1:



                            sed '$ d'


                            This is simple: if it's the last line, delete the pattern space, so it's not printed.




                          • If n is greater than 1 (and available as $n):



                            sed "
                            : start
                            1,$((n-1)) N; b start
                            $ t end; s/^//; D
                            N
                            P
                            D
                            : end
                            "


                            Note $((n-1)) is expanded by the shell before sed starts.



                            This fragment



                            : start
                            1,$((n-1)) N; b start


                            stores n-1 lines in the pattern space. If sed reaches the end of the input stream during this loop, the pattern space will be printed automatically (there is no n-th line from the end, no line will be deleted).



                            Suppose there is more input. Then, before we get to the last line, this fragment is iterated:



                            N # read the next line of input and append it to the pattern space
                            P # print the first line from the pattern space
                            D # delete the first line from the pattern space and start a new cycle


                            This way the pattern space is our buffer which makes the output several lines "late" according to the input. N from this fragment is able to read the last line of the input as well.



                            After the last line is read, this gets executed:



                            $ t end; s/^//; D 


                            When this code is executed for the first time, t doesn't branch to end because there was no successful substitution before. Such no-op substitution s/^// is then performed and the first line from the pattern space is deleted (D) without being printed. This is exactly the line you want to be deleted. Since D starts a new cycle, the same line of code will eventually be executed again. This time t will branch to end.



                            When sed reaches the end of the script, the pattern space is printed automatically. This way all remaining lines get printed.



                            The command will generate the same output for n=2 (valid) and n=1 (invalid). I tried to find a single solution that works regardless of n. I failed, hence the special case when your n is 1.








                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered 2 days ago









                          Kamil MaciorowskiKamil Maciorowski

                          1,82711030




                          1,82711030





















                              2














                              This is tagged with sed and awk but the question doesn't mention these as being required for the solution. Here's a Perl filter which removes the 4th-from-last line and prints the result. The output can written to a tmp file and then used to replace the original.



                               perl -e '@L = <STDIN>; splice(@L,-4,1); print @L' ./lines.txt





                              share|improve this answer





























                                2














                                This is tagged with sed and awk but the question doesn't mention these as being required for the solution. Here's a Perl filter which removes the 4th-from-last line and prints the result. The output can written to a tmp file and then used to replace the original.



                                 perl -e '@L = <STDIN>; splice(@L,-4,1); print @L' ./lines.txt





                                share|improve this answer



























                                  2












                                  2








                                  2







                                  This is tagged with sed and awk but the question doesn't mention these as being required for the solution. Here's a Perl filter which removes the 4th-from-last line and prints the result. The output can written to a tmp file and then used to replace the original.



                                   perl -e '@L = <STDIN>; splice(@L,-4,1); print @L' ./lines.txt





                                  share|improve this answer















                                  This is tagged with sed and awk but the question doesn't mention these as being required for the solution. Here's a Perl filter which removes the 4th-from-last line and prints the result. The output can written to a tmp file and then used to replace the original.



                                   perl -e '@L = <STDIN>; splice(@L,-4,1); print @L' ./lines.txt






                                  share|improve this answer














                                  share|improve this answer



                                  share|improve this answer








                                  edited 2 days ago









                                  glenn jackman

                                  53.2k573114




                                  53.2k573114










                                  answered 2 days ago









                                  Mark StosbergMark Stosberg

                                  4,1031227




                                  4,1031227





















                                      2














                                      if $n hold number of line to delete



                                      to delete a single line use



                                      printf "$-%d+1,$-%d+1dnwqn" $n $n| ed -s file


                                      to delete n last lines



                                      printf "$-%d,$dnwqn" $n | ed -s file


                                      where




                                      • $%d,$d tell ed to delete n last lines (printf will insert n)


                                      • wq write and quit

                                      • -s in ed -s will keep ed silent.


                                      • note that no provision is made to check you have enough line to delete.


                                      sadly range from end can't be specified in sed ...






                                      share|improve this answer

























                                      • What do you mean you can't specify ranges with sed? sed '2,4d' works fine on my end..

                                        – Panki
                                        2 days ago











                                      • I like to add -s to the call to ed; quiets the output a bit.

                                        – Jeff Schaller
                                        2 days ago











                                      • @JeffSchaller done

                                        – Archemar
                                        2 days ago















                                      2














                                      if $n hold number of line to delete



                                      to delete a single line use



                                      printf "$-%d+1,$-%d+1dnwqn" $n $n| ed -s file


                                      to delete n last lines



                                      printf "$-%d,$dnwqn" $n | ed -s file


                                      where




                                      • $%d,$d tell ed to delete n last lines (printf will insert n)


                                      • wq write and quit

                                      • -s in ed -s will keep ed silent.


                                      • note that no provision is made to check you have enough line to delete.


                                      sadly range from end can't be specified in sed ...






                                      share|improve this answer

























                                      • What do you mean you can't specify ranges with sed? sed '2,4d' works fine on my end..

                                        – Panki
                                        2 days ago











                                      • I like to add -s to the call to ed; quiets the output a bit.

                                        – Jeff Schaller
                                        2 days ago











                                      • @JeffSchaller done

                                        – Archemar
                                        2 days ago













                                      2












                                      2








                                      2







                                      if $n hold number of line to delete



                                      to delete a single line use



                                      printf "$-%d+1,$-%d+1dnwqn" $n $n| ed -s file


                                      to delete n last lines



                                      printf "$-%d,$dnwqn" $n | ed -s file


                                      where




                                      • $%d,$d tell ed to delete n last lines (printf will insert n)


                                      • wq write and quit

                                      • -s in ed -s will keep ed silent.


                                      • note that no provision is made to check you have enough line to delete.


                                      sadly range from end can't be specified in sed ...






                                      share|improve this answer















                                      if $n hold number of line to delete



                                      to delete a single line use



                                      printf "$-%d+1,$-%d+1dnwqn" $n $n| ed -s file


                                      to delete n last lines



                                      printf "$-%d,$dnwqn" $n | ed -s file


                                      where




                                      • $%d,$d tell ed to delete n last lines (printf will insert n)


                                      • wq write and quit

                                      • -s in ed -s will keep ed silent.


                                      • note that no provision is made to check you have enough line to delete.


                                      sadly range from end can't be specified in sed ...







                                      share|improve this answer














                                      share|improve this answer



                                      share|improve this answer








                                      edited 2 days ago

























                                      answered 2 days ago









                                      ArchemarArchemar

                                      20.7k93973




                                      20.7k93973












                                      • What do you mean you can't specify ranges with sed? sed '2,4d' works fine on my end..

                                        – Panki
                                        2 days ago











                                      • I like to add -s to the call to ed; quiets the output a bit.

                                        – Jeff Schaller
                                        2 days ago











                                      • @JeffSchaller done

                                        – Archemar
                                        2 days ago

















                                      • What do you mean you can't specify ranges with sed? sed '2,4d' works fine on my end..

                                        – Panki
                                        2 days ago











                                      • I like to add -s to the call to ed; quiets the output a bit.

                                        – Jeff Schaller
                                        2 days ago











                                      • @JeffSchaller done

                                        – Archemar
                                        2 days ago
















                                      What do you mean you can't specify ranges with sed? sed '2,4d' works fine on my end..

                                      – Panki
                                      2 days ago





                                      What do you mean you can't specify ranges with sed? sed '2,4d' works fine on my end..

                                      – Panki
                                      2 days ago













                                      I like to add -s to the call to ed; quiets the output a bit.

                                      – Jeff Schaller
                                      2 days ago





                                      I like to add -s to the call to ed; quiets the output a bit.

                                      – Jeff Schaller
                                      2 days ago













                                      @JeffSchaller done

                                      – Archemar
                                      2 days ago





                                      @JeffSchaller done

                                      – Archemar
                                      2 days ago











                                      1














                                      Neither standard sed nor awk support editing in place.



                                      For that, you better use ed(1) or ex(1):



                                      printf '$-%ddnwn' 1 | ed -s your_file


                                      Or with here-doc



                                      ed -s <<'EOT' your_file
                                      $-1d
                                      w
                                      EOT


                                      With advanced shells like bash, zsh orksh93 you can use the $'...' syntax and here-strings:



                                      ed -s <<<$'$-1dnw' your_file 


                                      Notice that the $ address means the last line from the file; so the index 1 there is 0-based; for the 1st line from the end replace the 1 with 0 ($-0), for the 3nd with 2 ($-2), etc.



                                      Putting it in a function:



                                      del_nth_line_from_end() ed -s "$1"; 


                                      Instead of ed -s you can use ex -s or vim -es everywhere.






                                      share|improve this answer





























                                        1














                                        Neither standard sed nor awk support editing in place.



                                        For that, you better use ed(1) or ex(1):



                                        printf '$-%ddnwn' 1 | ed -s your_file


                                        Or with here-doc



                                        ed -s <<'EOT' your_file
                                        $-1d
                                        w
                                        EOT


                                        With advanced shells like bash, zsh orksh93 you can use the $'...' syntax and here-strings:



                                        ed -s <<<$'$-1dnw' your_file 


                                        Notice that the $ address means the last line from the file; so the index 1 there is 0-based; for the 1st line from the end replace the 1 with 0 ($-0), for the 3nd with 2 ($-2), etc.



                                        Putting it in a function:



                                        del_nth_line_from_end() ed -s "$1"; 


                                        Instead of ed -s you can use ex -s or vim -es everywhere.






                                        share|improve this answer



























                                          1












                                          1








                                          1







                                          Neither standard sed nor awk support editing in place.



                                          For that, you better use ed(1) or ex(1):



                                          printf '$-%ddnwn' 1 | ed -s your_file


                                          Or with here-doc



                                          ed -s <<'EOT' your_file
                                          $-1d
                                          w
                                          EOT


                                          With advanced shells like bash, zsh orksh93 you can use the $'...' syntax and here-strings:



                                          ed -s <<<$'$-1dnw' your_file 


                                          Notice that the $ address means the last line from the file; so the index 1 there is 0-based; for the 1st line from the end replace the 1 with 0 ($-0), for the 3nd with 2 ($-2), etc.



                                          Putting it in a function:



                                          del_nth_line_from_end() ed -s "$1"; 


                                          Instead of ed -s you can use ex -s or vim -es everywhere.






                                          share|improve this answer















                                          Neither standard sed nor awk support editing in place.



                                          For that, you better use ed(1) or ex(1):



                                          printf '$-%ddnwn' 1 | ed -s your_file


                                          Or with here-doc



                                          ed -s <<'EOT' your_file
                                          $-1d
                                          w
                                          EOT


                                          With advanced shells like bash, zsh orksh93 you can use the $'...' syntax and here-strings:



                                          ed -s <<<$'$-1dnw' your_file 


                                          Notice that the $ address means the last line from the file; so the index 1 there is 0-based; for the 1st line from the end replace the 1 with 0 ($-0), for the 3nd with 2 ($-2), etc.



                                          Putting it in a function:



                                          del_nth_line_from_end() ed -s "$1"; 


                                          Instead of ed -s you can use ex -s or vim -es everywhere.







                                          share|improve this answer














                                          share|improve this answer



                                          share|improve this answer








                                          edited 2 days ago

























                                          answered 2 days ago









                                          mosvymosvy

                                          10.4k11238




                                          10.4k11238





















                                              0














                                              sed cannot calculate nth row from bottom by itself, so we need to that before, e.g. using awk:



                                              Delete 4th row from bottom:



                                              delrow=$(awk -v n=4 'END print NR-n+1 ' file)
                                              sed -i "$delrowd" file





                                              share|improve this answer



























                                                0














                                                sed cannot calculate nth row from bottom by itself, so we need to that before, e.g. using awk:



                                                Delete 4th row from bottom:



                                                delrow=$(awk -v n=4 'END print NR-n+1 ' file)
                                                sed -i "$delrowd" file





                                                share|improve this answer

























                                                  0












                                                  0








                                                  0







                                                  sed cannot calculate nth row from bottom by itself, so we need to that before, e.g. using awk:



                                                  Delete 4th row from bottom:



                                                  delrow=$(awk -v n=4 'END print NR-n+1 ' file)
                                                  sed -i "$delrowd" file





                                                  share|improve this answer













                                                  sed cannot calculate nth row from bottom by itself, so we need to that before, e.g. using awk:



                                                  Delete 4th row from bottom:



                                                  delrow=$(awk -v n=4 'END print NR-n+1 ' file)
                                                  sed -i "$delrowd" file






                                                  share|improve this answer












                                                  share|improve this answer



                                                  share|improve this answer










                                                  answered 2 days ago









                                                  RoVoRoVo

                                                  3,970317




                                                  3,970317





















                                                      0














                                                      An one-line, in-place solution:



                                                      With gawk, this will delete the 42nd line from the bottom:



                                                      gawk -i inplace 'i==0 if(FNR>t)t=FNRelsei=1 i==1 && FNR!=t-42 print' input input


                                                      The 42 can be replaced with any number. If 0 is used then the last line is deleted.



                                                      Notice that the input file is specified twice. This forces two iterations of the file with gawk. In the first iteration (i==0) the total number of lines (t) is established. In the second iteration, the nth line from the end is not output.



                                                      The file is modified in place by using the -i option.






                                                      share|improve this answer



























                                                        0














                                                        An one-line, in-place solution:



                                                        With gawk, this will delete the 42nd line from the bottom:



                                                        gawk -i inplace 'i==0 if(FNR>t)t=FNRelsei=1 i==1 && FNR!=t-42 print' input input


                                                        The 42 can be replaced with any number. If 0 is used then the last line is deleted.



                                                        Notice that the input file is specified twice. This forces two iterations of the file with gawk. In the first iteration (i==0) the total number of lines (t) is established. In the second iteration, the nth line from the end is not output.



                                                        The file is modified in place by using the -i option.






                                                        share|improve this answer

























                                                          0












                                                          0








                                                          0







                                                          An one-line, in-place solution:



                                                          With gawk, this will delete the 42nd line from the bottom:



                                                          gawk -i inplace 'i==0 if(FNR>t)t=FNRelsei=1 i==1 && FNR!=t-42 print' input input


                                                          The 42 can be replaced with any number. If 0 is used then the last line is deleted.



                                                          Notice that the input file is specified twice. This forces two iterations of the file with gawk. In the first iteration (i==0) the total number of lines (t) is established. In the second iteration, the nth line from the end is not output.



                                                          The file is modified in place by using the -i option.






                                                          share|improve this answer













                                                          An one-line, in-place solution:



                                                          With gawk, this will delete the 42nd line from the bottom:



                                                          gawk -i inplace 'i==0 if(FNR>t)t=FNRelsei=1 i==1 && FNR!=t-42 print' input input


                                                          The 42 can be replaced with any number. If 0 is used then the last line is deleted.



                                                          Notice that the input file is specified twice. This forces two iterations of the file with gawk. In the first iteration (i==0) the total number of lines (t) is established. In the second iteration, the nth line from the end is not output.



                                                          The file is modified in place by using the -i option.







                                                          share|improve this answer












                                                          share|improve this answer



                                                          share|improve this answer










                                                          answered 2 days ago









                                                          ltn100ltn100

                                                          22326




                                                          22326





















                                                              0














                                                              You can combine head and tail to achieve this.



                                                              If the nth line from the bottom needs to be deleted




                                                              1. head reads from standard input and reports to standard output total -n lines from the top


                                                              2. tail reads and reports to standard output the bottom n-1 lines from standard input.

                                                              3. Taken as a whole, the lines are thus reported to standard output in order, with the *nth` line from the end being skipped

                                                              This solution depends on head leaving the file offset of the open file description just after the last reported line - I believe GNU head does indeed do this when standard input is redirected from a file



                                                              n=200; tmpfile=$(mktemp) && head -n -$n; tail -n -$((n-1)); <file >"$tmpfile" 
                                                              && mv -- "$tmpfile" file





                                                              share|improve this answer



























                                                                0














                                                                You can combine head and tail to achieve this.



                                                                If the nth line from the bottom needs to be deleted




                                                                1. head reads from standard input and reports to standard output total -n lines from the top


                                                                2. tail reads and reports to standard output the bottom n-1 lines from standard input.

                                                                3. Taken as a whole, the lines are thus reported to standard output in order, with the *nth` line from the end being skipped

                                                                This solution depends on head leaving the file offset of the open file description just after the last reported line - I believe GNU head does indeed do this when standard input is redirected from a file



                                                                n=200; tmpfile=$(mktemp) && head -n -$n; tail -n -$((n-1)); <file >"$tmpfile" 
                                                                && mv -- "$tmpfile" file





                                                                share|improve this answer

























                                                                  0












                                                                  0








                                                                  0







                                                                  You can combine head and tail to achieve this.



                                                                  If the nth line from the bottom needs to be deleted




                                                                  1. head reads from standard input and reports to standard output total -n lines from the top


                                                                  2. tail reads and reports to standard output the bottom n-1 lines from standard input.

                                                                  3. Taken as a whole, the lines are thus reported to standard output in order, with the *nth` line from the end being skipped

                                                                  This solution depends on head leaving the file offset of the open file description just after the last reported line - I believe GNU head does indeed do this when standard input is redirected from a file



                                                                  n=200; tmpfile=$(mktemp) && head -n -$n; tail -n -$((n-1)); <file >"$tmpfile" 
                                                                  && mv -- "$tmpfile" file





                                                                  share|improve this answer













                                                                  You can combine head and tail to achieve this.



                                                                  If the nth line from the bottom needs to be deleted




                                                                  1. head reads from standard input and reports to standard output total -n lines from the top


                                                                  2. tail reads and reports to standard output the bottom n-1 lines from standard input.

                                                                  3. Taken as a whole, the lines are thus reported to standard output in order, with the *nth` line from the end being skipped

                                                                  This solution depends on head leaving the file offset of the open file description just after the last reported line - I believe GNU head does indeed do this when standard input is redirected from a file



                                                                  n=200; tmpfile=$(mktemp) && head -n -$n; tail -n -$((n-1)); <file >"$tmpfile" 
                                                                  && mv -- "$tmpfile" file






                                                                  share|improve this answer












                                                                  share|improve this answer



                                                                  share|improve this answer










                                                                  answered 2 days ago









                                                                  iruvariruvar

                                                                  12.5k63063




                                                                  12.5k63063




















                                                                      Swapnil Dhule is a new contributor. Be nice, and check out our Code of Conduct.









                                                                      draft saved

                                                                      draft discarded


















                                                                      Swapnil Dhule is a new contributor. Be nice, and check out our Code of Conduct.












                                                                      Swapnil Dhule is a new contributor. Be nice, and check out our Code of Conduct.











                                                                      Swapnil Dhule is a new contributor. Be nice, and check out our Code of Conduct.














                                                                      Thanks for contributing an answer to Unix & Linux Stack Exchange!


                                                                      • Please be sure to answer the question. Provide details and share your research!

                                                                      But avoid


                                                                      • Asking for help, clarification, or responding to other answers.

                                                                      • Making statements based on opinion; back them up with references or personal experience.

                                                                      To learn more, see our tips on writing great answers.




                                                                      draft saved


                                                                      draft discarded














                                                                      StackExchange.ready(
                                                                      function ()
                                                                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f512947%2fdelete-nth-line-when-counted-from-the-bottom%23new-answer', 'question_page');

                                                                      );

                                                                      Post as a guest















                                                                      Required, but never shown





















































                                                                      Required, but never shown














                                                                      Required, but never shown












                                                                      Required, but never shown







                                                                      Required, but never shown

































                                                                      Required, but never shown














                                                                      Required, but never shown












                                                                      Required, but never shown







                                                                      Required, but never shown







                                                                      Popular posts from this blog

                                                                      Get product attribute by attribute group code in magento 2get product attribute by product attribute group in magento 2Magento 2 Log Bundle Product Data in List Page?How to get all product attribute of a attribute group of Default attribute set?Magento 2.1 Create a filter in the product grid by new attributeMagento 2 : Get Product Attribute values By GroupMagento 2 How to get all existing values for one attributeMagento 2 get custom attribute of a single product inside a pluginMagento 2.3 How to get all the Multi Source Inventory (MSI) locations collection in custom module?Magento2: how to develop rest API to get new productsGet product attribute by attribute group code ( [attribute_group_code] ) in magento 2

                                                                      Category:9 (number) SubcategoriesMedia in category "9 (number)"Navigation menuUpload mediaGND ID: 4485639-8Library of Congress authority ID: sh85091979ReasonatorScholiaStatistics

                                                                      Magento 2.3: How do i solve this, Not registered handle, on custom form?How can i rewrite TierPrice Block in Magento2magento 2 captcha not rendering if I override layout xmlmain.CRITICAL: Plugin class doesn't existMagento 2 : Problem while adding custom button order view page?Magento 2.2.5: Overriding Admin Controller sales/orderMagento 2.2.5: Add, Update and Delete existing products Custom OptionsMagento 2.3 : File Upload issue in UI Component FormMagento2 Not registered handleHow to configured Form Builder Js in my custom magento 2.3.0 module?Magento 2.3. How to create image upload field in an admin form