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;
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
New contributor
add a comment |
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
New contributor
add a comment |
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
New contributor
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
awk sed perl
New contributor
New contributor
edited yesterday
Swapnil Dhule
New contributor
asked 2 days ago
Swapnil DhuleSwapnil Dhule
263
263
New contributor
New contributor
add a comment |
add a comment |
8 Answers
8
active
oldest
votes
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
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
add a comment |
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 beforesed
starts.This fragment
: start
1,$((n-1)) N; b startstores 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 cycleThis 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 toend
because there was no successful substitution before. Such no-op substitutions/^//
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. SinceD
starts a new cycle, the same line of code will eventually be executed again. This timet
will branch toend
.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) andn=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.
add a comment |
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
add a comment |
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
ined -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
...
What do you mean you can't specify ranges withsed
?sed '2,4d'
works fine on my end..
– Panki
2 days ago
I like to add-s
to the call toed
; quiets the output a bit.
– Jeff Schaller♦
2 days ago
@JeffSchaller done
– Archemar
2 days ago
add a comment |
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.
add a comment |
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
add a comment |
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.
add a comment |
You can combine head
and tail
to achieve this.
If the nth line from the bottom needs to be deleted
head
reads from standard input and reports to standard output total -n lines from the toptail
reads and reports to standard output the bottom n-1 lines from standard input.- 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
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
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
add a comment |
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
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
add a comment |
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
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
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
add a comment |
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
add a comment |
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 beforesed
starts.This fragment
: start
1,$((n-1)) N; b startstores 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 cycleThis 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 toend
because there was no successful substitution before. Such no-op substitutions/^//
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. SinceD
starts a new cycle, the same line of code will eventually be executed again. This timet
will branch toend
.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) andn=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.
add a comment |
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 beforesed
starts.This fragment
: start
1,$((n-1)) N; b startstores 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 cycleThis 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 toend
because there was no successful substitution before. Such no-op substitutions/^//
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. SinceD
starts a new cycle, the same line of code will eventually be executed again. This timet
will branch toend
.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) andn=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.
add a comment |
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 beforesed
starts.This fragment
: start
1,$((n-1)) N; b startstores 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 cycleThis 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 toend
because there was no successful substitution before. Such no-op substitutions/^//
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. SinceD
starts a new cycle, the same line of code will eventually be executed again. This timet
will branch toend
.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) andn=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.
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 beforesed
starts.This fragment
: start
1,$((n-1)) N; b startstores 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 cycleThis 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 toend
because there was no successful substitution before. Such no-op substitutions/^//
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. SinceD
starts a new cycle, the same line of code will eventually be executed again. This timet
will branch toend
.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) andn=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.
answered 2 days ago
Kamil MaciorowskiKamil Maciorowski
1,82711030
1,82711030
add a comment |
add a comment |
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
add a comment |
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
add a comment |
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
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
edited 2 days ago
glenn jackman
53.2k573114
53.2k573114
answered 2 days ago
Mark StosbergMark Stosberg
4,1031227
4,1031227
add a comment |
add a comment |
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
ined -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
...
What do you mean you can't specify ranges withsed
?sed '2,4d'
works fine on my end..
– Panki
2 days ago
I like to add-s
to the call toed
; quiets the output a bit.
– Jeff Schaller♦
2 days ago
@JeffSchaller done
– Archemar
2 days ago
add a comment |
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
ined -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
...
What do you mean you can't specify ranges withsed
?sed '2,4d'
works fine on my end..
– Panki
2 days ago
I like to add-s
to the call toed
; quiets the output a bit.
– Jeff Schaller♦
2 days ago
@JeffSchaller done
– Archemar
2 days ago
add a comment |
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
ined -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
...
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
ined -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
...
edited 2 days ago
answered 2 days ago
ArchemarArchemar
20.7k93973
20.7k93973
What do you mean you can't specify ranges withsed
?sed '2,4d'
works fine on my end..
– Panki
2 days ago
I like to add-s
to the call toed
; quiets the output a bit.
– Jeff Schaller♦
2 days ago
@JeffSchaller done
– Archemar
2 days ago
add a comment |
What do you mean you can't specify ranges withsed
?sed '2,4d'
works fine on my end..
– Panki
2 days ago
I like to add-s
to the call toed
; 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
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
edited 2 days ago
answered 2 days ago
mosvymosvy
10.4k11238
10.4k11238
add a comment |
add a comment |
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
add a comment |
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
add a comment |
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
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
answered 2 days ago
RoVoRoVo
3,970317
3,970317
add a comment |
add a comment |
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.
add a comment |
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.
add a comment |
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.
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.
answered 2 days ago
ltn100ltn100
22326
22326
add a comment |
add a comment |
You can combine head
and tail
to achieve this.
If the nth line from the bottom needs to be deleted
head
reads from standard input and reports to standard output total -n lines from the toptail
reads and reports to standard output the bottom n-1 lines from standard input.- 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
add a comment |
You can combine head
and tail
to achieve this.
If the nth line from the bottom needs to be deleted
head
reads from standard input and reports to standard output total -n lines from the toptail
reads and reports to standard output the bottom n-1 lines from standard input.- 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
add a comment |
You can combine head
and tail
to achieve this.
If the nth line from the bottom needs to be deleted
head
reads from standard input and reports to standard output total -n lines from the toptail
reads and reports to standard output the bottom n-1 lines from standard input.- 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
You can combine head
and tail
to achieve this.
If the nth line from the bottom needs to be deleted
head
reads from standard input and reports to standard output total -n lines from the toptail
reads and reports to standard output the bottom n-1 lines from standard input.- 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
answered 2 days ago
iruvariruvar
12.5k63063
12.5k63063
add a comment |
add a comment |
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.
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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