Append a string after digits in a file using sed - bash

I have a file containing these lines:
John
Some String 1234
Mary
another string 3445
Tom
Cat Dog 2367
i.e. every alternate line ends with number, and there are no numbers anywhere else.
I want to add < /br> tag just after the number so that output is like:
John
Some String 1234</br>
Mary
another string 3445</br>
...
I tried using sed command as:
sed -i 's/[0-9]+/1<\/br>/' filename.html
but it errors out.
How do I get this done?

You can use:
sed -i.bak 's~[0-9]\+$~&</br>~' file
Now file content will be:
cat file
John
Some String 1234</br>
Mary
another string 3445</br>
Tom
Cat Dog 2367</br>

Use this one:
sed 's/\([0-9]\+\)$/\1<br\/>/' your.txt
Short explanation:
Numbers with a various length [0-9]\+at the of the line $ gets matched into a matching-group \( ... \). It will get replaced by the value of that matching group \1 plus the <br\/> tag. Don't miss that I've escaped several characters with the backslash \ because they have a special meaning in the pattern.

Try this:
sed -ri.bak '/[0-9]+$/ s/$/<\/br>/g' filename.html

Got it, I was missing () around the matched pattern.
So it is like:
sed -i 's/\([0-9][0-9]*\)/\L\1<\/br>/I' filename.html

Since the numbers are always at the end of even numbered lines, GNU sed's extended range addresses are sufficient:
sed -i.bak '2~2s#$#</br>#' file
Output:
John
Some String 1234</br>
Mary
another string 3445</br>
Tom
Cat Dog 2367</br>

Related

How to Search for a String and replace the n to n+10 character from that string with another 10 character in Unix

I want to search for a string and then from that string i want to replace 10 characters with another 10 characters.
For Example,
/prd/edm/hadoop/ifrs/eglex/hdata/ifrs_sri_open/eglex_*_txnacbal/ods=2020_02_23/
i want to search for string "ods=" and replace "2020_02_23" with "2020_02_30"
Since that date "2020_02_23" is not consistent i wanted to search with "ods=" which is static and one time for a line.
Like this more lines are there in the file.
I tried:
cat dta_1.sh | sed 's/.*ods=//' | cut -c1-10
I want to search for string "ods=" and replace "2020_02_23" with
"2020_02_30"
sed 's|\(.*ods=\).*|\12020_02_30/|g' inputfile
The regex inside the parenthesis \( \) is reproduced by \1, and the string after ods= is replaced by 2020_02_30/.
If there could be something else besides / after the date, then go for this:
sed 's|\(.*ods=\)...._.._..|\12020_02_30|g' inputfile
I've completed this using the below,
sed -i '/ods=/ s|ods="[^"]*"|ods='"${DATE_FORMAT2}"'|g' dta_2.sh
Thanks all for the response

bash script: how to insert text between two specific characters

For example, I have a file containing a line as below:
"abc":"def"
I need to insert 123 between "abc":" and def" so that the line will become: "abc":"123def".
As "abc" appears only once so I think I can just search it and do the insertion.
How to do this with bash script such as sed or awk?
AMD$ sed 's/"abc":"/&123/' File
"abc":"123def"
Match "abc":", then append this match with 123 (& will contain the matched string "abc":")
If you want to take care of space before and after :, you can use:
sed 's/"abc" *: *"/&123/'
For replacing all such patterns, use g with sed.
sed 's/"abc" *: *"/&123/g' File
sed:
$ sed -E 's/(:")(.*)/\1123\2/' <<<'"abc":"def"'
"abc":"123def"
(:") gets :" and put in captured group 1
(.*) gets the remaining portion and put in captured group 2
in the replacement, \1123\2 puts 123 between the groups
awk:
$ awk -F: 'sub(".", "&123", $2)' <<<'"abc":"def"'
"abc" "123def"
In the sub() function, the second ($2) field is being operated on, pattern is used as . (which would match "), and in the replacement the matched portion (&) is followed by 123.
echo '"abc":"def"'| awk '{sub(/def/,"123def")}1'
"abc":"123def"

sed not working as expected (trying to get value between two matches in a string)

I have a file (/tmp/test) the has a the string "aaabbbccc" in it
I want to extract "bbb" from the string with sed.
Doing this returns the entire string:
sed -n '/aaa/,/ccc/p' /tmp/test
I just want to return bbb from the string with sed (I am trying to learn sed so not interested in other solutions for this)
Sed works on a line basic, and a,b{action} will run action for lines matching a until lines matching b. In your case
sed -n '/aaa/,/ccc/p'
will start printing lines when /aaa/ is matched, and stop when /ccc/ is matched which is not what you want.
To manipulate a line there is multiply options, one is s/search/replace/ which can be utilized to remove the leading aaa and trailing ccc:
% sed 's/^aaa\|ccc$//g' /tmp/test
bbb
Breakdown:
s/
^aaa # Match literal aaa in beginning of string
\| # ... or ...
ccc$ # Match literal ccc at the end of the sting
// # Replace with nothing
g # Global (Do until there is no more matches, normally when a match is
# found and replacement is made this command stops replacing)
If you are not sure how many a's and c's you have you can use:
% sed 's/^aa*\|cc*$//g' /tmp/test
bbb
Which will match literal a followed by zero or more a's at the beginning of the line. Same for the c's but just at the end.
With GNU sed:
sed 's/aaa\(.*\)ccc/\1/' /tmp/test
Output:
bbb
See: The Stack Overflow Regular Expressions FAQ

sed - Replacing brackets with characters?

I have a string that with brackets that enclose a single character, like such:
[a]
I want to take the character within the bracket and replace the bracket with the character, so the end result would look like:
aaa
This is what I came up with, but it doesn't work:
sed 's/\[ \([a-z]\) \]/\2/g' < testfile
Can someone please help me, and explain why my command isn't working?
Try the following code:
$ echo "[a]" | sed 's/\[\([a-zA-Z]\)\]/\1\1\1/g'
or
$ echo "[a]" | sed -r 's/\[([a-zA-Z])\]/\1\1\1/g'
Output:
aaa
I think you missed some basic concepts. First let's duplicate a single char
$ echo a | sed -r 's/(.)/\1\1/'
aa
parenthesis indicates the groups and \1 refers to the first group
Now, to match a char in square brackets and triple it.
$ echo [a]b | sed -r 's/\[(.)\]/\1\1\1/'
aaab
you need to escape square bracket chars since they have special meaning in regex. The key is you have to bracket in parenthesis the regex you're interested in and refer to them in the same order with \{number} notation.
The issue with your patern sed 's/\[ \([a-z]\) \]/\2/g' < testfile:
1) The pattern has only one group \([a-z]\), so \2 is invalid;
2) The pattern contains space, there is no match found;
3) To replace brackets, you need to capture them in a group.
My idea is, to catch all groups in a pattern, and replace them with \2\2\2:
echo "[a]" | sed 's/\(\[\)\([a-z]\)\(\]\)/\2\2\2/g'
Or
echo "[a]" | sed 's/\(.\)\(.\)\(.\)/\2\2\2/g'
The output is:
aaa

SED - Replace trailing minus sign

Good Evening,
I'm trying to replace a trailing minus sign with a leading minus sign. The link below was very helpful, but I'm having a hard time dealing with both a comma and period. For example:
Input Data:
|76534| 253,453.86-| 6/4/2012| 56487-56987|
|32567| 36,000.00| 7/8/2012| 45684-4541|
|58531| 400.56-| 10/5/2012| 15232-1254|
|12584| 5.56-| 12/12/2013| 125565-451|
Desired Results (all other columns remain the same):
-253,453.86
36,000.00
-400.56
-5.56
Using sed -r 's/([[:digit:]]+(\,[[:digit:]]+(\.[[:digit:]]+)?))-/-\1/' I've been able to treat numbers with a comma, but I would like to treat all types in one command if possible.
Helpful Link:
Replace a trailing minus with leading minus
This seems to work with your multi-column data:
sed -r '{s#([0-9][0-9,.]*)-\|#-\1\|#g}'
Use [[:digit:],.] to create a character class with numbers, commas and periods. The rest you already know how to do.
sed -r 's/([[:digit:].,])-/-\1/'
You can do:
$ sed '/-$/{s/-$//;s/[0-9]/-&/;b};s/^/ /' file
-253,453.86
36,000.00
-400.56
-5.56
Updated Answer:
$ awk 'BEGIN{FS=OFS="|"}{for(i=1;i<=NF;i++)if($i~/-$/){sub(/-$/,"",$i);sub(/[0-9]/,"-&",$i)}}1' file
|76534| -253,453.86| 6/4/2012| 56487-56987|
|32567| 36,000.00| 7/8/2012| 45684-4541|
|58531| -400.56| 10/5/2012| 15232-1254|
|12584| -5.56| 12/12/2013| 125565-451|
$ awk 'BEGIN{FS=OFS="|"} sub(/-$/,"",$3){sub(/[^ ]/,"-&",$3)}1' file
|76534| -253,453.86| 6/4/2012| 56487-56987|
|32567| 36,000.00| 7/8/2012| 45684-4541|
|58531| -400.56| 10/5/2012| 15232-1254|
|12584| -5.56| 12/12/2013| 125565-451|
Another one through GNU sed,
$ sed -r 's/^(\|[0-9]+\|)( *?)([^|]*?)(-)(.*)$/\1\2\4\3\5/g' file
|76534| -253,453.86| 6/4/2012| 56487-56987|
|32567| 36,000.00| 7/8/2012| 45684-4541|
|58531| -400.56| 10/5/2012| 15232-1254|
|12584| -5.56| 12/12/2013| 125565-451|
A simple solution:
sed 's/\([^ ]*\)\-|/-\1|/' input

Resources