How to toggle a comment in a line using sed - linux

I have a txt file with a line I want to comment, I am using sed
comment out
sed -i 's/line1/#line1/' myfile.ini
uncomment out
sed -i 's/#line1/line1/' myfile.ini
this works but the problem is that sometimes I run this twice by mistake, and I end up with a line like
##line1
so when I run the uncomment command, the line is now
#line1
is there an alternative to toggle the comment? this is inside a bash script so I am happy to add a few lines if necessary.
thanks

You can use this sed command:
sed -i 's/^[[:blank:]]*line1/#&/' myfile.ini
Here matching pattern is ^[[:blank:]]*line1 which means match start of line followed by 0 or more whitespace characters before matching line1. And replacement is #& to place # before matched string.
Similarly for uncommenting use:
sed -Ei 's/^#([[:blank:]]*line1)/\1/' myfile.ini
Which matches # at line start followed by 0 or more whitespaces before matching line1. It capture part after # in capture group #1 and uses back-reference \1 in replacement to remove just the # part.

Building Upon #Anubhava's Answer,
You can combine the two into a One-Liner to Toggle comments with:
sed -Ei 's/^[[:blank:]]*line1/#&/;t;s/^#([[:blank:]]*line1)/\1/' myfile.ini
For MacOS/OSX and Other BSD Systems, You can do:
sed -Ei'' 's/^[[:blank:]]*line1/#&/;t;s/^#([[:blank:]]*line1)/\1/' myfile.ini
This is a simple "if-else" statement in sed.
More About Sed Branching & Flow Control Here

Related

How to use sed to replace a filename in text file

I have a file:
dynamicclaspath.cfg
VENDOR_JAR=/clear-as-1-d/apps/sterling/jar/struts/2_5_18/1_0_0/log4j-core-2.10.0.jar
VENDOR_JAR=/clear-as-1-d/apps/sterling/jar/log4j/2_17_1/log4j-core-2.10.0.jar
I want to replace any occurrence of log4j-core* with log4j-core-2.17.1.jar
I tried this but I know I'm missing a regex:
sed -i '/^log4j-core/ s/[-]* /log4j-core-2.17.1.jar/'
With your shown samples please try following sed program. Using -E option with sed to enable ERE(extended regular expressions) with it. In main program using substitute option to perform substitution. Using sed's capability to use regex and store matched values into temp buffer(capturing groups). Matching till last occurrence of / and then matching log4j-core till jar at last of value. While substituting it with 1st capturing group value(till last occurrence of /) followed by new value of log4j as per OP's requirement.
sed -E 's/(^.*\/)log4j-core-.*\.jar$/\1log4j-core-2.17.1.jar/' Input_file
Using sed
$ sed -E 's/(log4j-core-)[0-9.]+/\12.17.1./' input_file
VENDOR_JAR=/clear-as-1-d/apps/sterling/jar/struts/2_5_18/1_0_0/log4j-core-2.17.1.jar
VENDOR_JAR=/clear-as-1-d/apps/sterling/jar/log4j/2_17_1/log4j-core-2.17.1.jar
It depends on possible other contents in your input file how specific the search pattern must be.
sed 's/log4j-core-.*\.jar/log4j-core-2.17.1.jar/' inputfile
or
sed 's/log4j-core-[0-9.]*\.jar/log4j-core-2.17.1.jar/' inputfile
or (if log4j-core*.jar is always the last part of the line)
sed 's/log4j-core.*/log4j-core-2.17.1.jar/' inputfile
sed -i s'#2.10.0.jar$#2.17.1.jar#'g file
That seems to work.

Add many quotation in sed instruction

I have to update line with value containg many quotation characters
sed -i 's/.*sonar.links.issue.*/property "sonar.links.issue", "http://jra.url"'
I get error there. What should i do to do it correctly?
Your replacement string contains slashes "http://", so you shouldn't use / as the delimiter for this sed command, use # as shellter proposes.
To complete its answer, I would add the "g" flag, at the end of the sed expression, to ensure the subsitution is made on the whole line, and not only on the first match with ".sonar.links.issue.".
sed -i 's#.*sonar.links.issue.*#property "sonar.links.issue", "http://jra.url"#g' file
Try
sed -i 's#.*sonar.links.issue.*#property "sonar.links.issue", "http://jra.url"#' file
IHTH

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.

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.

sed replace string in a first line

How can I replace a string but only in the first line of the file using the program "sed"?
The commands s/test/blah/1 and 1s/test/blah/ don't seem to work. Is there another way?
This might work for you (GNU sed):
sed -i '1!b;s/test/blah/' file
will only substitute the first test for blah on the first line only.
Or if you just want to change the first line:
sed -i '1c\replacement' file
This will do it:
sed -i '1s/^.*$/Newline/' textfile.txt
Failing that just make sure the match is unique to line one only:
sed -i 's/this is line one and its unique/Changed line one to this string/' filename.txt
The -i option writes the change to the file instead of just displaying the output to stdout.
EDIT:
To replace the whole line by matching the common string would be:
sed -i 's/^.*COMMONSTRING$/Newline/'
Where ^ matches the start of the line, $ matches the end of the line and .* matches everything upto COMMONSTRING
this replaces all matches, not just the first match, only in the first line of course:
sed -i '1s/test/blah/g' file
the /g did the trick to replace more than one matches, if any exists.

Resources