简体   繁体   中英

Delete a character from second last line in unix

How can we remove character from second last line of a file in unix?

For example I have a file with content as follows:

aaa
bbb*
ccc*
ddd*
eee

my output should be :

aaa
bbb*
ccc*
ddd
eee

any ideas on this?

The generic way to do this in a single pass with sed is to use a sliding window, similar to what is described in the GNU sed manual .

As you are only interested in a substitution on the second to last line there is no need for hold space. In this case a single N will suffice:

sed 'N; $! { P; D; }; s/.\n/\n/'

Or as a BSD sed compatible script:

sed 'N; $! { P; D; }; s/.\n/\
/'

Output:

aaa
bbb*
ccc*
ddd
eee

Explanation

  • The N command adds a second line to pattern space.
  • The $! block is evaluated when we have not reached the last line.
  • { P; D; } { P; D; } prints the first line of pattern space and deletes it. The D has a side-effect of restarting the script if pattern space is not empty.
  • The substitution command is only evaluated when the last two lines are in pattern space.

There are three general approaches that spring to mind.

Use wc -l file to get the number of lines:

awk 'NR==n-1{sub(/.$/,"")}1' n=$(wc -l file)
aaa
bbb*
ccc*
ddd
eee

Parse the file twice:

awk 'FNR==NR{n++;next}FNR==n-1{sub(/.$/,"")}1' file file
aaa
bbb*
ccc*
ddd
eee

Reverse the file before and after processing:

tac file | sed '2s/.$//' | tac
aaa
bbb*
ccc*
ddd
eee

nice time to re-use ed , for once :

the short version:

{ echo '$-1s/.$//' ; echo "w" ; } | ed file_to_modify.txt >/dev/null

version with some "debugging info" ^^ :

{ echo 'doing: $-1s/.$//' >&2 ; echo '$-1s/.$//' ; echo "doing: w" >&2 ; echo "w" ; echo "C" >&2 ; } | ed file_to_modify.txt

in a nutshell : ed is very close to vi, but works on 1 line at a time... I just tell it to 's/.$//' (replace last char of a line by nothing) on the n-1th line ($= last line in ed, and $-1 = last line - 1)

使用vivim或任何编辑器打开文件,然后根据需要编辑文件

straightforward with awk:

awk '{a[NR]=$0}END{for(i=1;i<=NR;i++){if(i==NR-1)sub(/.$/,"",a[i]);print a[i]}}' file

a bit tricky way with awk:

awk '{if(f>1)print p;p=l;f++;l=$0}END{sub(/.$/,"",p);print p;print l}' file

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM