How can I replace the final character in a document with a ]? - fish

How can I replace the final character of a file with a ]?
For example, if the document content looked like this:
This is the first line with a full stop.
This is the second line with a full stop.
This is the third line with square bracket.
I would want it to look like this afterwards:
This is the first line with a full stop.
This is the second line with a full stop.
This is the third line with square bracket]

You may specify line numbers, ranges or even the last line where you want to perform search and replace operations with sed:
This will replace the final , char with ] only on the last line:
sed '$ s/,$/]/'
Here, the $ char tells sed to only replace on the last line.
The sed '1 s/,$/]/' command will do that only on Line 1, and sed '1,4 s/,$/]/' will do that on lines 1 through 4.

Related

How does this sed command: "sed -e :a -e '$d;N;2,10ba' -e 'P;D' " work?

I saw a sed command to delete the last 10 rows of data:
sed -e :a -e '$d;N;2,10ba' -e 'P;D'
But I don't understand how it works. Can someone explain it for me?
UPDATE:
Here is my understanding of this command:
The first script indicates that a label “a” is defined.
The second script indicates that it first determines whether the
line currently reading pattern space is the last line. If it is,
execute the "d" command to delete it and restart the next cycle; if
not, skip the "d" command; then execute "N" command: append a new
line from the input file to the pattern space, and then execute
"2,10ba": if the line currently reading the pattern space is a line
in the 2nd to 10th lines, jump to label "a".
The third script indicates that if the line currently read into
pattern space is not a line from line 2 to line 10, first execute "P" command: the first line
in pattern space is printed, and then execute "D" command: the first line in pattern
space is deleted.
My understanding of "$d" is that "d" will be executed when sed reads the last line into the pattern space. But it seems that every time "ba" is executed, "d" will be executed, regardless of Whether the current line read into pattern space is the last line. why?
:a is a label. $ in the address means the last line, d means delete. N stands for append the next line into the pattern space. 2,10 means lines 2 to 10, b means branch (i.e. goto), P prints the first line from the pattern space, D is like d but operates on the pattern space if possible.
In other words, you create a sliding window of the size 10. Each line is stored into it, and once it has 10 lines, lines start to get printed from the top of it. Every time a line is printed, the current line is stored in the sliding window at the bottom. When the last line gets printed, the sliding window is deleted, which removes the last 10 lines.
You can modify the commands to see what's getting deleted (()), stored (<>), and printed by the P ([]):
$ printf '%s\n' {1..20} | \
sed -e ':a ${s/^/(/;s/$/)/;p;d};s/^/</;s/$/>/;N;2,10ba;s/^/[/;s/$/]/;P;D'
[<<<<<<<<<<1>
[<2>
[<3>
[<4>
[<5>
[<6>
[<7>
[<8>
[<9>
[<10>
(11]>
12]>
13]>
14]>
15]>
16]>
17]>
18]>
19]>
20])
a simpler resort, if your data in 'd' file by gnu sed,
sed -Ez 's/(.*\n)(.*\n){10}$/\1/' d
^
pointed 10 is number of last line to remove
just move the brace group to invert, ie. to get only the last 10 lines
sed -Ez 's/.*\n((.*\n){10})$/\1/' d

How to replace the nth occurrence of a sttring in a file using sed [duplicate]

This question already has answers here:
How to replace the nth occurrence of a string using sed
(2 answers)
Closed 8 years ago.
Is there any way to replace the nth occurrence of a string in a file using sed?
How can i change it so that it replaces the nth occurrence?
My file contents the following lines:
first line
second line
third line
jack
fifth line
jack
seventh line
consider a variable var = jill.
I want to replace the 2nd occurrence of jack with value of variable $var.
This might work for you (GNU sed):
sed ':a;$!{N;ba};s/jack/'"$var"'/2' file
This slurps the file into memory and then substitutes the second occurence of jack for $var.
EDIT:
:a is a place holder for a b command, it tell sed to break/jump to position i.e ba jump to :a.
$! is an address. $ means end of file and ! means not. Put together this means any address which is not-the-end-of-file.
{...} groups the commands between the braces.
N appends a newline and then the next line to the pattern space except when there are no more lines when it passes sed to just passed the last command (if the -n is not set it will print what ever is in the pattern space, if -n is set it will just end processing).
s/jack/'$var"'/2 this is a sed substitution command and replaces the second occurrence of jack by the contents of $var. N.B. the '...' which effectively breaks out sed commands into the underlying shell and then back again allowing the shell variable to be interpolated.
In summary the whole file is slurped into memory and the second occurrence of jack is replaced by the contents of $var.
In most cases this could by replaced by:
sed -z 's/jack/'"$var"'/2' file
Here is an awk version if you like to use awk
awk -v c="$var" '/jack/ && ++a==2 {sub(/jack/,c)}1' file
first line
second line
third line
jack
fifth line
jill
seventh line

SED inserting a blank line below a line

I want to add a black line below a line ending in a period.
I have sed '/ REGEX goes here/G' I'm not sure how to replace the regex to except a period as expression to look for.
I want to add a blank line below each sentence here's an example of some text I would want to use the sed shell script on.
Line one.
The second line.
The third.
This is line four.
five.
This is the sixth sentence.
This is line seven.
Eighth and last.
Try following sed
sed 's/\.$/.\n/' file
EDIT (after comments of #Jotne)
If you have any spaces after . at the end of line, adding \s* would be safe.
sed 's/\.\s*$/.\n/' file
I'm not sure how to replace the regex to except a period as expression
to look for.
You can say:
sed '/\.$/G' filename
Escape the . so as to match a literal .; the anchor $ ensures that the matched . was at the end of line.

How to replace the nth occurrence of a string using sed

Is there any way to replace the nth occurrence of a string in a file using sed?
I'm using sed -i '0,/jack.*/ s//jill/' to replace the first occurrence.
How can i change it so that it replaces the nth occurrence?
My file contents the following lines:
first line
second line
third line
jack=1
fifth line
jack=
seventh line
I don't know the value after jack=, it can be anything or nothing.
I want to replace the 2nd occurrence of jack= and anything that follows it with jill.
First replace all the newlines with a unique character that does not occur anywhere else in your file (e.g. ^) using tr. You need to do this in order to create a single string for sed. Then pass it to sed and tell it to replace the nth occurrence of your string. Finally, pass the output back through tr to recreate the newlines.
For n=2, the command is:
$ tr '\n' '^' < file | sed 's/jack/jill/2' | tr '^' '\n'
first line
second line
third line
jack
fifth line
jill
seventh line
Update:
It can also be done with sed, WITHOUT changing the newlines first, using the following command:
$ sed ':a;N;$!ba;s/jack/jill/2' file
Alternatively, use awk:
$ awk '/jack/{c+=1}{if(c==2){sub("jack","jill",$0)};print}' file
Try this, sed ':a;N;$!ba;s/word1/word2/n' filename
Here, :a;N;$!ba is used to load the entire file into memory, line by line, so that sed can process the whole file in a single pass. The s/word1/word2/N substitution then replaces every Nth occurrence of word1 with word2.

In a sed transformation, how to apply a slightly different pattern just for the last line?

How can I turn this:
aaa
bbb
ccc
into this:
aaa,
bbb,
ccc
using sed?
Note how all lines end a comma, except the last one.
In my real problem I also do some regex substitutions on the lines. Is there a solution that doesn't duplicate them?
You could use:
sed '$q;s/$/,/'
If you want to apply a different substitution on the last line, you can still use the $ address:
sed '$s/$/;/;$q;s/$/,/'
The above will replace the end of the line with ; if it's the last line, otherwise it will use ,.
$s/$/;/ = at the last line, replace the end of the line with ;
$q = at the last line, quit
s/$/,/ = replace the end of the line with ,
The last s command will run for each line, but not for the last line in which the q command at 2. tells it to quit.
See:
Restricting to a line number
Ranges by line number
The q or quit command