Max_IT
Max_IT

Reputation: 638

sed and regular expression: unexpected replacement pattern

I am trying to use a small bash script using sed to append a string, but I do not seem to be able to make it work. I want to append a string to another string pattern:

Strings in input file:

Xabc
Xdef

Desired output:

XabcZ
XdefZ

Here is the script:

#!/bin/bash
instring="$2"
sed -r "s/${instring}/${instring}Z/g" $1

Where $1 is the file name and $2 is the string pattern I am looking for

Then I run the script:

bash script.test.sh test.txt X

output:

XZabc
XZdef

As expected. but if I use regular expressions:

bash script.test.sh test.txt X...

All I get is:

X...Z
X...Z

So obviously it is not reading it correctly in the replacement part of the command. Smae thing if I use X[a-z09] (but there may be "_" in my strings, I want to include those as well). I had a look at several previous similar topics, but I do not seem able to implement any of the solutions correctly (bear with a newbie...). Thank you for your kind help.

EDIT: After receiving the answers from Glenn Jackman (accepted solution) and RavinderSingh13, I would like to clarify two important points for whoever is having a similar issue:

1) Glenn Jackman solution did not work because I needed to convert the text file from DOS to Unix. I did it with dos2unix , but for some reason did not work (maybe forgot to overwrite the output to the old file?). I later did it using sed -i 's/\r$//' test.txt ; that solved the issue, and Glenn's solution now works. having a dos-formatted text file has been the source of many trouble, for me at least.

2) I probably did not make clear that I only wanted to target specific lines in the input files; my example only has target strings, but the actual file has strings that I do not want to edit. That was probably the misunderstanding occurred with RavinderSingh13's script, which actually works, but targets every single line. Hope this can help future readers. Thank you, Stackers, you saved the day once again :)

Upvotes: 2

Views: 481

Answers (2)

RavinderSingh13
RavinderSingh13

Reputation: 133770

EDIT: In case you need to pass a regex to script then following may help, where my previous solution was only appending a character to last of the line.

cat script.ksh
value="$2"
sed  "s/$value/&Z/"  "$1"

After running the script:

./script.ksh X.*
XabcZ
XdefZ

After seeing OP's comment to match everything which starts from either small letter or capital letter run script in following style then.

./script.ksh [A-Za-z]+*


Could you please try following and let me know if this helps you.

cat script.ksh
value="$2"
sed "s/$/$value/" "$1"

After running script I am getting following output on terminal too.

./script.ksh Input_file Z
XabcZ
XdefZ

You could use sed -i option in above code in case you want to save output into Input_file itself too.

Upvotes: 2

glenn jackman
glenn jackman

Reputation: 247210

What you have (sed -r "s/${instring}/${instring}Z/g" $1) uses the variable as a pattern on the left-hand side and as plain text on the right-hand side.

What you want to do is:

sed -r "s/${instring}/&Z/g" $1
# ....................^

where the & marker is replaced by whatever text the pattern matched. In the documentation for The s Command:

[T]he replacement can contain unescaped & characters which reference the whole matched portion of the pattern space.

Upvotes: 3

Related Questions