How to add text with sed at the end-of-line minus 1 position - linux

I want to add the text [*,test,*] just before the last character of a line starting with resourceFilters: in the input file (that string can be preceded by any number of spaces).
An example of this line is the following
resourceFilters: '[Event,*,*][*,kube-system,*][*,kube-public,*][*,kube-node-lease,*][Node,*,*][APIService,*,*][TokenReview,*,*][SubjectAccessReview,*,*][Binding,*,*][ReplicaSet,*,*]'
which would be changed into this:
resourceFilters: '[Event,*,*][*,kube-system,*][*,kube-public,*][*,kube-node-lease,*][Node,*,*][APIService,*,*][TokenReview,*,*][SubjectAccessReview,*,*][Binding,*,*][ReplicaSet,*,*][*,test,*]'

sed "/^ *resourceFilters: '/s/'$/[*,test,*]'/" your_file
I've double quoted the Sed command so that I can use single quotes in it;
/^resourceFilters: '/ makes the following substitution command only act on lines starting with resourceFilters: ';
s/'$/[*,test,*]'/ is the substitution command which matches ' at end of line ($), and substitutes [*, test,*]' to it, effectively inserting [*,test,*] before the '.

This might work for you (GNU sed):
sed -E 's/^(\s*resourceFilters:.*)(.)$/\1[*,test,*]\2/' file
Match on a line containing resourceFilters: and insert [*,test,*] before the last character of the line.

Related

SED - insert a blank line after every input line that consists of capital letters and spaces

I have a text file and I need a command using sed to insert a blank line after every line that that consists of capital letters and spaces only.
This might work for you (GNU sed):
sed '/^[[:blank:][:upper:]][[:blank:][:upper:]]*$/G' file
This appends the hold space (by default it contains a newline) to lines containing at least one or more whitespace or uppercase characters.
Given:
$ cat file
LINE LINE LINE
Line Line Line
Line 1
LINE 2
END!
====
You can use s/// to add a \n to the line:
With POSIX sed, use a literal new line in the sed script:
$ sed 's/^\([[:upper:][:blank:]]*\)$/\1\
/' file
LINE LINE LINE
Line Line Line
Line 1
LINE 2
END!
====
With GNU sed, you can use the representation of \n:
$ sed 's/^\([[:upper:][:blank:]]*\)$/\1\n/' file
You can also use a\ to append in sed. I have tried to get sed append to work but cannot reliably with POSIX, BSD and GNU sed since POSIX and BSD do not support \n
With GNU sed (note space after a\):
$ sed '/^[[:upper:][:blank:]]*$/a\ ' file
BSD:
$ sed '/^[[:upper:][:blank:]]*$/a\
\
' file
Those are not exactly equivalent since the GNU version has a space on the blank line.
The version of POSIX sed I have did not work with either of those...
Given the platform and version differences of sed, you might consider awk to do this since simple awk's are easier to make universal.
This works on every awk I have:
$ awk '1; /^[[:upper:][:blank:]]*$/{print ""}' file
With awk you can also make it so that blank lines are not doubled by making sure there is at least non blank like so:
$ awk '1; /^[[:upper:][:blank:]]+$/ && NF>1 {print ""}' file
Sure. Just insert lines with a:
sed '/^[[:blank:]A-Z]*$/a\'
The a command inserts the string after it after every matching line (end the string with a backslash). So the above command just inserts an empty line after all lines that contains solely of capital letters and spaces. That's exactly what you want.

sed command to delete starting pattern match with special character in it

I have sed command that delete line when string match with starting pattern
sed -i "/^Data\=C\b/Id" tally.ini
This work correctly for patch Data=C
But I want to match path Data=C:\ and that I want to delete this line.
How can this possible?
sed -i '/^Data\=C:\\/Id' tally.ini
Put the command in a single quoted string instead of double.
Escape the backslash.

delete and replace a line using linux command

I am trying to delete a line with the pattern matches and replacing the entire line with the another line using sed command.
File contents:Sample.txt
Testfile=xxxx
Testfile3=uuuu
Testfile4=oooo
Testfile5=iiii
Testfile2=ikeii
I am using sed command to delete a line contains Testfile3=* and replace by Testfile3=linechanged
sed -i 's/Testfile3=\*/Testfile3=linechanged/' Sample.txt.
But it just appends the replaceable string in the line as shown below
Testfile3=linechanged=uuuu.
I am expecting the output to be
Testfile3=linechanged.
What i am doing wrong?
The star is not matched right:
sed -i 's/Testfile3=.*/Testfile3=linechanged/' Sample.txt
# ^^
.* matches any character (.) for any length (*), so it will match everything till the end of the line.
You can use captured group to keep what will be preserved and use the desired replacement for the rest:
sed -i 's/^\(Testfile3=\).*/\1linechanged/' file.txt
In your case, escaping the Regex token * like \* will match * literally e.g. Testfile3=* would be matched then.
This might work for you (GNU sed):
sed '/Testfile3/cTestfile3=linechanged' file
This matches the line containing Testfile3 and changes it to the required string.

sed can't differentiate CR from LF if both exist in the same file

I have a file where CR (\r) and LF (\n) exists in the same file.
a1 a2 CRLF
b1 LF
b2 CRLF
c1 c2 CRLF
The file need to be fixed to:
a1 a2 CRLF
b1 b2 CRLF
c1 c2 CRLF
The logic is simple: remove LF that is not preceded by CR with empty string:
sed 's/[^\r]\n//g' input.txt > output.txt
However, this doesn't work!
I had to delete all the occurrences of LF, and replace all the remaining CR with CRLF :
cat input.txt | tr -d '\n' | sed 's/\r/\r\n/g' >output.txt
this bugs me. why isn't sed working??
#Etan Reisner is basically correct - sed handles text as newline-delimited lines, so you need to jump through some hoops to make it deal with newlines directly. Just because you can do this doesn't mean it's the cleanest way, but if you don't have other tools at your disposal, here's an example of how to do this:
sed -e 's/[^\r]$/&/' -e te -e b -e :e -e N -e 's/\n//'
What this command does is:
s/[^\r]$/&/ - replace a CR at the end of a line with ... itself.
te - test and branch: if the previous substitution succeeded, branch to the indicated label. (We needed it to succeed, which is why it substituted with itself)
b - unconditionally branch to the end of the script
:e - create a label for the earlier te command to jump to
N - append the next line into the pattern space. This results in a pattern space with an embedded newline.
s/\n// - delete the embedded newline.
sed doesn't see line endings in the line it is operating on.
This is the same reason that sed 's/\n//' doesn't give you a file with only one line.
The newlines are handled "internally".
This is the sort of task that dos2unix/unix2dos/etc. may handle for you more directly.
I'd use awk:
awk -v RS='\r\n' 'BEGIN { ORS = RS } { gsub(/\n/, ""); print }'
With the record separator RS set to \r\n, the file will be split into records separated by, well, \r\n, so removing newlines in those records removes all newlines that are not preceded by \r. Setting ORS (the output record separator) to RS makes it so that the output file still has CRLF line endings.
Note that multi-character RS is not strictly POSIX-conforming. The most common awks support it, though.
Or there's the Perl way:
perl -pe 's/(?<!\r)\n//'
This relies on a negative lookbehind; (?<!\r) matches an empty string that is not preceded by \r. Note that unlike sed, Perl without -l does not remove newlines from the input, so no special tricks are necessary to remove them.

Inserting string in file in nth line after pattern using sed

I want to insert word after nth line after pattern using sed.
I tied to modify this command but it inserts only in first line after pattern.
sed -i '/myPattern/a \ LineIWantToinser ' myFile
What command should I use to insert for example in third line after pattern?
Easiest way to do it with GNU sed is.. (maybe some direct solution exists!?)
sed -n '/pattern/=' file
to see line where pattern is (grep also can be used here with -n)
then if linenumber+ numoflines is for example 123
sed '123aSOME INSERTED TEXT AFTER THAT LINE' file
where little a is append command (after that line, if i is used will be pre pattern line)
ps. I'm eager to see if #neronlevelu (or other sed Lover) will find some better sed solution.
Edit: i've found it, it seems a for append or i for insert must? be on first position on line when using { with ; inside } like
sed '/pattern/{N;N;N;
a SOME TEXT FOR INSERTING
}' file
sed '/pattern/{N;N;N;i \
Line to add after 3 lines with patterne as starting counter
' YourFile
number of N to add line between pattern and inserted line.
there is no check for end of file or pattern in the 3 lines. (not specified in PO)
A version with bash and ed:
ed -s myFile <<<$'/myPattern/+3a\n LineIWantToinser \n.\nwq'
ed enables us to use the line addressing /myPattern/+3.

Resources