How to use Sed to replace specific characters - bash

How to use Sed to replace all bold characters? (for example from 0200 to 0300)
the whole command is in one line
NSun0000-0000Mon0200+2130Tue0200+2130Wed0200+2130Thu0200+2130Fri0200+2130Sat0000-0000
This must be a universal command because the digits can change (but will always be in the same place).

Assuming you have Bash and you want to change each one to 0300.
ubuntu$ sed -E 's/([a-zA-Z]{3})([0-9]{4})/\10300/g' text.txt
NSun0300-0000Mon0300+2130Tue0300+2130Wed0300+2130Thu0300+2130Fri0300+2130Sat0300-0000
Regards!

Related

Use a shell script to replace text with pwd

file.txt
...
<LOCAL_PATH_TO_REPO>/src/java/example.java
...
^A longer file but this pretty much explains what I am trying to do.
script.sh
dir=$(pwd)
# replace <LOCAL_PATH_TO_REPO> with dir
I tried using the sed command but it did not work for some reason. Any ideas on how to do this?
Your error means you have backslashes in the variable text.
The simplest solution is to change the delimiter to the one that does not occur in the variable text.
If there are no commas use a comma:
sed -i "s,LOCAL_PATH_TO_REPO,$PWD," file.yml
The -i flag introduces changes into the input file (works for GNU sed).

Replacing text with shell script ending with an extension

I need some inputs on how to achieve this:
I need to replace a text in a file, using shell script, the text which i need to replace ends with .ear, for example below:
/home/export/files/list/aa_bb_cc.ear
The shell script should replace the aa_bb_cc.ear with say, replaced.ear.
That is the line after substitution should be:
/home/export/files/list/replaced.ear
I did read online about this, and came to know about sed command. The problem which i have, is that i don't know before hand what the text to be replace would be, that is, i know the text to be replace would be something *.ear (in an attempt to match aa_bb_cc.ear)
Now, how can I do this? I tried to use "*" in sed however it didn't work
With GNU sed:
sed 's|[^/]*\.ear|replaced.ear|' file
or
sed 's|[^/]*\(\.ear\)|replaced\1|' file
If you want to edit your file "in place" use sed's option -i.
See: The Stack Overflow Regular Expressions FAQ
$ echo /home/export/files/list/aa_bb_cc.ear | sed 's/[^/]*\.ear/xxx.ear/'
/home/export/files/list/xxx.ear
since regex match is greedy, you need to specify to match non-slash char. Dot matches any char, so to specify literal dot you have to escape with back-slash.

Removing chars until a numeric is found from array item Bash

I have the line of text within a text file. The line looks something like this:
xxxx,xxxxx,xxxxxx,xxxxx,xxxx,NL-1111 xx,xxxx,xxx
The NL- is an identifier for the country so this could be anything. I would like to remove the NL- part from the line so it looks like this:
xxxx,xxxxx,xxxxxx,xxxxx,xxxx,1111 xx,xxxx,xxx
And write the file afterwards.
Thanks in advance.
Another solution close to sed's ones, but with perl:
perl -i -pe "s/(?<=,)[a-zA-Z]{2}-//g" file.txt
It uses look behind expression, so that you don't need to repeat the comma in the replacement part.
something like this using sed
sed -i 's/,[A-Z][A-Z]-\([0-9]\+,\)/,\1/i' file.txt
,[A-Z][A-Z]-\([0-9]\+,\)search for comma letter, letter, -, digit(s), comma
,\1keep only the commas and the digits.
iignore case on the letters
thankyou to #chris for proof-reading.
I think the simplest solution here is reading it from the file into a shell variable, then writing it back immediately and using the pattern substitution variation of parameter expansion:
line="$(<file)"; echo "${line/[a-zA-Z][a-zA-Z]-}" >|file;
I would warn you against solutions that use sed-in-place functionality. I've found that sed behavior differs on different platforms with respect to the -i option. On Mac you have to give an empty argument ('') to the -i option, while on Cygwin you must not have an empty argument following the -i. To get platform compatibility you'd have to test what platform you're on.
sed might do the trick: remove the string ",NL-", "BE-" etc from anywhere in the file:
sed -i 's/,[A-Z][A-Z]-/,/' file.txt

How to replace all spaces in .txt file using SED in Cygwin

I have a huge .txt file that I want all spaces, line-breaks, indentations etc removed. It should literally be one long string.
I tried
sed -i 's/\ //g' test.txt
but nothing happens
sed -n "s/[[:blank:]]//g;H
$ {x;s/\n//g;p;}"
The H than $ are needed if you want to include New line due to fact that sed treat by default line by line (so no new line inside a line). The -n and p are needed to avoid double display with use of H
Seems to work ok for me:
[~/Desktop]
==> cat test.txt
the quick brown fox
[~/Desktop]
==> sed -i "s/\ //g" test.txt
[~/Desktop]
==> cat test.txt
thequickbrownfox
Sometimes using " " directly is hard and especially when you use double quotes (which involves that bash will interpret the string before passing it to sed).
sed -i -e 's/\s//g' file.txt
... should work (it works for me). "\s" means all whitespace characters, and with single quotes '', for bash not to interpret it before you passing it to sed.
While you use cygwin I think your OS is windows, then you don't need to use bash to implement your goal. Just open your txt file with the text editor, and replace the while space with nothing, then all of the whit space in you txt file will be removed.
This method can meet almost all kinds of removal. And also can apply in excel or word and so on.
Good luck!

Insert line after match using sed

For some reason I can't seem to find a straightforward answer to this and I'm on a bit of a time crunch at the moment. How would I go about inserting a choice line of text after the first line matching a specific string using the sed command. I have ...
CLIENTSCRIPT="foo"
CLIENTFILE="bar"
And I want insert a line after the CLIENTSCRIPT= line resulting in ...
CLIENTSCRIPT="foo"
CLIENTSCRIPT2="hello"
CLIENTFILE="bar"
Try doing this using GNU sed:
sed '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file
if you want to substitute in-place, use
sed -i '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file
Output
CLIENTSCRIPT="foo"
CLIENTSCRIPT2="hello"
CLIENTFILE="bar"
Doc
see sed doc and search \a (append)
Note the standard sed syntax (as in POSIX, so supported by all conforming sed implementations around (GNU, OS/X, BSD, Solaris...)):
sed '/CLIENTSCRIPT=/a\
CLIENTSCRIPT2="hello"' file
Or on one line:
sed -e '/CLIENTSCRIPT=/a\' -e 'CLIENTSCRIPT2="hello"' file
(-expressions (and the contents of -files) are joined with newlines to make up the sed script sed interprets).
The -i option for in-place editing is also a GNU extension, some other implementations (like FreeBSD's) support -i '' for that.
Alternatively, for portability, you can use perl instead:
perl -pi -e '$_ .= qq(CLIENTSCRIPT2="hello"\n) if /CLIENTSCRIPT=/' file
Or you could use ed or ex:
printf '%s\n' /CLIENTSCRIPT=/a 'CLIENTSCRIPT2="hello"' . w q | ex -s file
Sed command that works on MacOS (at least, OS 10) and Unix alike (ie. doesn't require gnu sed like Gilles' (currently accepted) one does):
sed -e '/CLIENTSCRIPT="foo"/a\'$'\n''CLIENTSCRIPT2="hello"' file
This works in bash and maybe other shells too that know the $'\n' evaluation quote style. Everything can be on one line and work in
older/POSIX sed commands. If there might be multiple lines matching the CLIENTSCRIPT="foo" (or your equivalent) and you wish to only add the extra line the first time, you can rework it as follows:
sed -e '/^ *CLIENTSCRIPT="foo"/b ins' -e b -e ':ins' -e 'a\'$'\n''CLIENTSCRIPT2="hello"' -e ': done' -e 'n;b done' file
(this creates a loop after the line insertion code that just cycles through the rest of the file, never getting back to the first sed command again).
You might notice I added a '^ *' to the matching pattern in case that line shows up in a comment, say, or is indented. Its not 100% perfect but covers some other situations likely to be common. Adjust as required...
These two solutions also get round the problem (for the generic solution to adding a line) that if your new inserted line contains unescaped backslashes or ampersands they will be interpreted by sed and likely not come out the same, just like the \n is - eg. \0 would be the first line matched. Especially handy if you're adding a line that comes from a variable where you'd otherwise have to escape everything first using ${var//} before, or another sed statement etc.
This solution is a little less messy in scripts (that quoting and \n is not easy to read though), when you don't want to put the replacement text for the a command at the start of a line if say, in a function with indented lines. I've taken advantage that $'\n' is evaluated to a newline by the shell, its not in regular '\n' single-quoted values.
Its getting long enough though that I think perl/even awk might win due to being more readable.
A POSIX compliant one using the s command:
sed '/CLIENTSCRIPT="foo"/s/.*/&\
CLIENTSCRIPT2="hello"/' file
Maybe a bit late to post an answer for this, but I found some of the above solutions a bit cumbersome.
I tried simple string replacement in sed and it worked:
sed 's/CLIENTSCRIPT="foo"/&\nCLIENTSCRIPT2="hello"/' file
& sign reflects the matched string, and then you add \n and the new line.
As mentioned, if you want to do it in-place:
sed -i 's/CLIENTSCRIPT="foo"/&\nCLIENTSCRIPT2="hello"/' file
Another thing. You can match using an expression:
sed -i 's/CLIENTSCRIPT=.*/&\nCLIENTSCRIPT2="hello"/' file
Hope this helps someone
The awk variant :
awk '1;/CLIENTSCRIPT=/{print "CLIENTSCRIPT2=\"hello\""}' file
I had a similar task, and was not able to get the above perl solution to work.
Here is my solution:
perl -i -pe "BEGIN{undef $/;} s/^\[mysqld\]$/[mysqld]\n\ncollation-server = utf8_unicode_ci\n/sgm" /etc/mysql/my.cnf
Explanation:
Uses a regular expression to search for a line in my /etc/mysql/my.cnf file that contained only [mysqld] and replaced it with
[mysqld]
collation-server = utf8_unicode_ci
effectively adding the collation-server = utf8_unicode_ci line after the line containing [mysqld].
I had to do this recently as well for both Mac and Linux OS's and after browsing through many posts and trying many things out, in my particular opinion I never got to where I wanted to which is: a simple enough to understand solution using well known and standard commands with simple patterns, one liner, portable, expandable to add in more constraints. Then I tried to looked at it with a different perspective, that's when I realized i could do without the "one liner" option if a "2-liner" met the rest of my criteria. At the end I came up with this solution I like that works in both Ubuntu and Mac which i wanted to share with everyone:
insertLine=$(( $(grep -n "foo" sample.txt | cut -f1 -d: | head -1) + 1 ))
sed -i -e "$insertLine"' i\'$'\n''bar'$'\n' sample.txt
In first command, grep looks for line numbers containing "foo", cut/head selects 1st occurrence, and the arithmetic op increments that first occurrence line number by 1 since I want to insert after the occurrence.
In second command, it's an in-place file edit, "i" for inserting: an ansi-c quoting new line, "bar", then another new line. The result is adding a new line containing "bar" after the "foo" line. Each of these 2 commands can be expanded to more complex operations and matching.

Resources