Sed substitute: make a group operator optional - sed

Let's say I want to use sed to substitute expressions like "foo", "foo(1 1)", "foo(42 1)" by "bar". I tried :
sed -i ':a;N;$!ba;s/foo([0-9]\+ [0-9]\+)\{0,1\}/bar/g' input.file
But only replaced expressions with parenthesis after foo, not foo with no parenthesis.
Do you have any idea why ?
Example of I wish:
INPUT
foo
foo(236 124)
OUPUT
bar
bar

You can use this sed:
sed 's/foo\(([0-9]\+ [0-9]\+)\)\{0,1\}/bar/g' file
^ ^
Here, I have added grouping. So that, {0,1} would work exactly.
Test:
$ sed 's/foo\(([0-9]\+ [0-9]\+)\)\{0,1\}/bar/g' file
bar
bar

With GNU sed:
sed -E 's/foo(\([0-9]+ [0-9]+\))?/bar/' file

Related

How to replace # using sed c0mmand?

I have the following header :
#SRR1561197.1/1
#SRR1561197.2/1
#SRR1561197.3/1
#SRR1561197.4/1
I want to Add few letters after # and before SRR like this:
#MexD1SRR1561197.1/1
#MexD1SRR1561197.2/1
#MexD1SRR1561197.3/1
#MexD1SRR1561197.4/1
I tried:
sed 's/#/#MexD1/File,fastq > change.fastq
This results in empty file..
Use sed with the in file replacement option. The g at the end makes it global.
sed -i 's/#/#MexD1/g' file
To fix your code.
sed 's/#/#MexD1/g' File.fastq > change.fastq
You have to escape it: sed s/\#/\#MexD1/g source-file-name > change.fastq

sed substitute with quotes and wildcard

I need to replace if ($_SESSION['POST']['*']==1){ with if (isset($_SESSION['POST']['*']) && $_SESSION['POST']['*']==1){
(I'm using * as a wild card)
I've tried sed -i "s/if ($_SESSION['POST']['.*']/if (isset($_SESSION['POST']['.*']) && $_SESSION['POST']['.*']/g" *.php and a few other variations without success.
Here goes...
sed "s/\(if (\)\(\$_SESSION\['POST']\['\([^']*\)']\)==1/\1isset(\2) \&\& \$_SESSION['POST']['\3']==1/" file
Using double quotes means that the $ symbols must be escaped, otherwise they will be interpreted as shell variables. The square brackets need to be escaped, otherwise they will be interpreted as the beginning of a range. It's OK to leave the closing square brackets as they are.
In order to capture the key, I have used a character class [^']*. This means zero or more characters that are not a single quote.
In the replacement, the captured groups (the parts between parentheses in the match) are referred to using \1, \2, etc.
Testing it out:
$ cat file
if ($_SESSION['POST']['foo']==1){
// do something
}
if ($_SESSION['POST']['bar']==1){
// do something else
}
$ sed "s/\(if (\)\(\$_SESSION\['POST']\['\([^']*\)']\)==1/\1isset(\2) \&\& \$_SESSION['POST']['\3']==1/" file
if (isset($_SESSION['POST']['foo']) && $_SESSION['POST']['foo']==1){
// do something
}
if (isset($_SESSION['POST']['bar']) && $_SESSION['POST']['bar']==1){
// do something else
}
By the way it makes the command a few characters shorter if you use extended regexp mode (-r or -E). In extended mode, the parentheses enclosing capture groups don't have to be escaped but literal ones do, so your command would then be:
sed -r "s/(if \()(\$_SESSION\['POST']\['([^']*)'])==1/\1isset(\2) \&\& \$_SESSION['POST']['\3']==1/" file
This sed should work:
s="if (\$_SESSION['POST']['name']==1){"
sed -r 's/(if +)\((([^=]+)[^\)]+)/\1(isset(\3) \&\& \2/' <<< "$s"
if (isset($_SESSION['POST']['name']) && $_SESSION['POST']['name']==1){
PS: Use sed -E instead of sed -r on OSX.
Here's another.
This is what we need to produce:
Pattern: if (\$_SESSION\['POST'\]\['\([^']*\)'\]
Replacement: if (isset($_SESSION['POST']['\1']) \&\& $_SESSION['POST']['\1']
When quoted in shell level:
Pattern: "if (\\\$_SESSION\['POST'\]\['\([^']*\)'\]"
Replacement: "if (isset(\$_SESSION['POST']['\1']) \\&\\& \$_SESSION['POST']['\1']"
Putting it together:
sed -i "s|if (\\\$_SESSION\['POST'\]\['\([^']*\)'\]|if (isset(\$_SESSION['POST']['\1']) \\&\\& \$_SESSION['POST']['\1']|g" file
Test:
# sed "s|if (\\\$_SESSION\['POST'\]\['\([^']*\)'\]|if (isset(\$_SESSION['POST']['\1']) \\&\\& \$_SESSION['POST']['\1']|g" <<'EOF'
> if ($_SESSION['POST']['ABC']==1){
> EOF
if (isset($_SESSION['POST']['ABC']) && $_SESSION['POST']['ABC']==1){

How can replace this using sed?

I'm using OS X, want to replace
[self.lang getAppLanguageString:#"foo bar"]
to
LocalizedString(#"foo bar", nil)
I use sed like the below:
sed -i '' s/[self\.lang getAppLanguageString:#"([a-zA-Z]+)"]/LocalizedString(#"\1", nil)/g somefile
but not work, how can I do that?
You've already escaped . in the pattern, but also need to escape [ and ].
Try:
sed -i 's/\[self\.lang getAppLanguageString:#\("[^"]*"\)\]/LocalizedString(#\1, nil)/' somefile

Is it possible to tell sed to perform a maximum of one substitution per line?

Is it possible to encapsulate the following pseudocode using sed?
for line in lines:
if line == "foo":
print "FOO"
else:
print "- " + line
Here's the first thing I tried:
> echo 'foo
> bar
> baz' | sed -e 's/^foo$/FOO/' -e 's/^/- /'
- FOO
- bar
- baz
This is incorrect since both substitutions are applied to the first line.
Is it possible to tell sed to perform a maximum of one substitution per line?
You can limit what lines a substitution affects, by prefixing it with a pattern:
sed -e '/^foo$/! s/^/- /' -e '/^foo$/ s//FOO/' infile
A better alternative is to use the t branch command which will go to the next line if the previous substitution succeeded:
sed 's/^foo$/FOO/; t; s/^/- /' infile
Or the more portable:
sed -e 's/^foo$/FOO/' -e t -e 's/^/- /' infile
Output in both cases:
FOO
- bar
- baz

sed replace if part of word matches

My text looks like this:
cat
catch
cat_mouse
catty
I want to replace "cat" with "dog".
When I do
sed "s/cat/dog/"
my result is:
dog
catch
cat_mouse
catty
How do I replace with sed if only part of the word matches?
There's a mistake :
You lack the g modifier
sed 's/cat/dog/g'
g
Apply the replacement to all matches to the regexp, not just the first.
See
http://www.gnu.org/software/sed/manual/html_node/The-_0022s_0022-Command.html
http://sed.sourceforge.net/sedfaq3.html#s3.1.3
If you want to replace only cat by dog only if part of the word matches :
$ perl -pe 's/cat(?=.)/dog/' file.txt
cat
dogch
dog_mouse
dogty
I use Positive Look Around, see http://www.perlmonks.org/?node_id=518444
If you really want sed :
sed '/^cat$/!s/cat/dog/' file.txt
bash-3.00$ cat t
cat
catch
cat_mouse
catty
To replace cat only if it is part of a string
bash-3.00$ sed 's/cat\([^$]\)/dog\1/' t
cat
dogch
dog_mouse
dogty
To replace all occurrences of cat:
bash-3.00$ sed 's/cat/dog/' t
dog
dogch
dog_mouse
dogty
awk solution for this
awk '{gsub("cat","dog",$0); print}' temp.txt