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's the connection between Mr. Nancy and fried chicken?

Compiling and throwing simple dynamic exceptions at runtime for JVM

Putting Ant-Man on house arrest

Why does BitLocker not use RSA?

Can 'non' with gerundive mean both lack of obligation and negative obligation?

Can the van der Waals coefficients be negative in the van der Waals equation for real gases?

How to break 信じようとしていただけかも知れない into separate parts?

What is her name?

Why are two-digit numbers in Jonathan Swift's "Gulliver's Travels" (1726) written in "German style"?

Etymology of 見舞い

Will I be more secure with my own router behind my ISP's router?

Is "ein Herz wie das meine" an antiquated or colloquial use of the possesive pronoun?

How to charge percentage of transaction cost?

When speaking, how do you change your mind mid-sentence?

Coin Game with infinite paradox

How to get a single big right brace?

lm and glm function in R

What is the difference between 准时 and 按时?

Do chord progressions usually move by fifths?

How to mute a string and play another at the same time

Why did Israel vote against lifting the American embargo on Cuba?

2 sample t test for sample sizes - 30,000 and 150,000

What helicopter has the most rotor blades?

Weaponising the Grasp-at-a-Distance spell



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 Apr 18 at 9:17







      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 Apr 17 at 8:53









      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
            Apr 17 at 9:09






          • 2





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

            – Panki
            Apr 17 at 9:17


















          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
                Apr 17 at 9:20











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

                – Jeff Schaller
                Apr 17 at 15:45











              • @JeffSchaller done

                – Archemar
                Apr 17 at 18:36


















              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
                        Apr 17 at 9:09






                      • 2





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

                        – Panki
                        Apr 17 at 9:17















                      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
                        Apr 17 at 9:09






                      • 2





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

                        – Panki
                        Apr 17 at 9:17













                      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 Apr 17 at 18:22









                      glenn jackman

                      53.3k573115




                      53.3k573115










                      answered Apr 17 at 8:57









                      PankiPanki

                      1,030514




                      1,030514












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

                        – Swapnil Dhule
                        Apr 17 at 9:09






                      • 2





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

                        – Panki
                        Apr 17 at 9:17

















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

                        – Swapnil Dhule
                        Apr 17 at 9:09






                      • 2





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

                        – Panki
                        Apr 17 at 9:17
















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

                      – Swapnil Dhule
                      Apr 17 at 9:09





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

                      – Swapnil Dhule
                      Apr 17 at 9:09




                      2




                      2





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

                      – Panki
                      Apr 17 at 9:17





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

                      – Panki
                      Apr 17 at 9:17













                      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 Apr 17 at 12:03









                          Kamil MaciorowskiKamil Maciorowski

                          1,86211030




                          1,86211030





















                              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 Apr 17 at 18:25









                                  glenn jackman

                                  53.3k573115




                                  53.3k573115










                                  answered Apr 17 at 13:48









                                  Mark StosbergMark Stosberg

                                  4,1131227




                                  4,1131227





















                                      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
                                        Apr 17 at 9:20











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

                                        – Jeff Schaller
                                        Apr 17 at 15:45











                                      • @JeffSchaller done

                                        – Archemar
                                        Apr 17 at 18:36















                                      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
                                        Apr 17 at 9:20











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

                                        – Jeff Schaller
                                        Apr 17 at 15:45











                                      • @JeffSchaller done

                                        – Archemar
                                        Apr 17 at 18:36













                                      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 Apr 17 at 18:36

























                                      answered Apr 17 at 9:12









                                      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
                                        Apr 17 at 9:20











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

                                        – Jeff Schaller
                                        Apr 17 at 15:45











                                      • @JeffSchaller done

                                        – Archemar
                                        Apr 17 at 18:36

















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

                                        – Panki
                                        Apr 17 at 9:20











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

                                        – Jeff Schaller
                                        Apr 17 at 15:45











                                      • @JeffSchaller done

                                        – Archemar
                                        Apr 17 at 18:36
















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

                                      – Panki
                                      Apr 17 at 9:20





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

                                      – Panki
                                      Apr 17 at 9:20













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

                                      – Jeff Schaller
                                      Apr 17 at 15:45





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

                                      – Jeff Schaller
                                      Apr 17 at 15:45













                                      @JeffSchaller done

                                      – Archemar
                                      Apr 17 at 18:36





                                      @JeffSchaller done

                                      – Archemar
                                      Apr 17 at 18:36











                                      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 Apr 17 at 15:55

























                                          answered Apr 17 at 15:24









                                          mosvymosvy

                                          10.6k11338




                                          10.6k11338





















                                              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 Apr 17 at 9:25









                                                  RoVoRoVo

                                                  3,980317




                                                  3,980317





















                                                      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 Apr 17 at 13:02









                                                          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 Apr 17 at 14:25









                                                                  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

                                                                      Sum ergo cogito? 1 nng

                                                                      三茅街道4182Guuntc Dn precexpngmageondP