LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   BASH: how to substitute a expression with another without creating a new file (https://www.linuxquestions.org/questions/linux-newbie-8/bash-how-to-substitute-a-expression-with-another-without-creating-a-new-file-769456/)

carolflb 11-16-2009 09:58 AM

BASH: how to substitute a expression with another without creating a new file
 
Hi guys,

I'm writting a script in BASH and I want to find the expression "int foo[i] = true;" in a text and substitute it by the word "boo[i]= true;", but without erasing other words from the text and without having to create a new file. Would somebody know how I can do that?

Text for example:

whi(&M§)/&§M)POM;M;(29073()/§()"/§;();§/()"7§ZE/§)&§=)"&/=)$&=!&$=!
waxe83qmi3u,jy,einure,xl9me23uy9, int foo[i] = true;i23904802y97p,94280
u2908/M="(§?;$(/EZ"Zolsdwiea,ru8
q2xi4l9i<ey93
2x5093405
int foo[i]= true;
39i2e09ui9,y92ßi049.

acid_kewpie 11-16-2009 10:19 AM

sed -i -e 's/int\ foo\[i\]=true\;/something\ else/g' myfile

TBH, the escape characters mightn't be exactly correct, but it's the -i option for sed you're really looking for.

carolflb 11-16-2009 10:30 AM

Hi Cris!

That works perfectly. Thanks a lot ;)

Actually would you also know how can I tell 'sed' to substitute just the first match?

acid_kewpie 11-16-2009 12:03 PM

well the "g" makes sed do multiple replacements in the same line, so if you remove that it'll only do it once per line.

stevenworr 11-16-2009 10:35 PM

Why execute sed as an external process when bash can just do it inline?

Code:

#! /bin/bash

match='int foo\[i\] = true;'
while read line
do
    [[ "$line"  =~ "$match" ]] && line="${line/$match/something else}"
    echo "$line"
done

Quote:

${parameter/pattern/string}
The pattern is expanded to produce a pattern just as in pathname
expansion. Parameter is expanded and the longest match of pat-
tern against its value is replaced with string. If Ipattern
begins with /, all matches of pattern are replaced with string.
Normally only the first match is replaced. If pattern begins
with #, it must match at the beginning of the expanded value of
parameter. If pattern begins with %, it must match at the end
of the expanded value of parameter. If string is null, matches
of pattern are deleted and the / following pattern may be omit-
ted. If parameter is @ or *, the substitution operation is
applied to each positional parameter in turn, and the expansion
is the resultant list. If parameter is an array variable sub-
scripted with @ or *, the substitution operation is applied to
each member of the array in turn, and the expansion is the
resultant list.

ghostdog74 11-16-2009 10:55 PM

Code:

$  more file
whi(&M§)/&§M)POM;M;(29073()/§()"/§;();§/()"7§ZE/§)&§=)"&/=)$&=!&$=!
waxe83qmi3u,jy,einure,xl9me23uy9, int foo[i] = true;i23904802y97p,94280
u2908/M="(§?;$(/EZ"Zolsdwiea,ru8
q2xi4l9i<ey93
2x5093405
int foo[i]= true;
39i2e09ui9,y92ßi049.
int  foo[i]    =    true
the end

$ awk '{gsub(/int[ ]+foo\[i\][ ]*=[ ]*true/,"---")}1' file

whi(&M§)/&§M)POM;M;(29073()/§()"/§;();§/()"7§ZE/§)&§=)"&/=)$&=!&$=!
waxe83qmi3u,jy,einure,xl9me23uy9, ---;i23904802y97p,94280
u2908/M="(§?;$(/EZ"Zolsdwiea,ru8
q2xi4l9i<ey93
2x5093405
---;
39i2e09ui9,y92ßi049.
---
the end


ghostdog74 11-16-2009 10:58 PM

Quote:

Originally Posted by stevenworr (Post 3759520)
Why execute sed as an external process when bash can just do it inline?

Code:

#! /bin/bash

match='int foo\[i\] = true;'
while read line
do
    [[ "$line"  =~ "$match" ]] && line="${line/$match/something else}"
    echo "$line"
done


these will not match:
Code:

1) int foo[i]= true
2) int    foo[i]  =  true
3) int foo[i] =true


stevenworr 11-17-2009 01:09 AM

Quote:

Originally Posted by ghostdog74 (Post 3759540)
these will not match:
Code:

1) int foo[i]= true
2) int    foo[i]  =  true
3) int foo[i] =true


You have to give bash what it wants to do the job. You can make this as hard as you want or only as hard as you need.
Code:

match=$'int[ \t]+foo\[i\][ \t]*=[ \t]*true[ \t]*;'
Then you can do stuff like

Code:

[[ "$line" =~ "$match" ]] && line="int boo[i] = true;
Feel free to add as many extra paren groupies to exactly preserve as much whitespace as you need.

If you really want to go ape

Code:

match=$'int([ \t]+)foo\[i\]([ \t]*=[ \t]*)true([ \t]*);'
[[ "$line" =~ "$match" ]] && line="int${BASH_REMATCH[1]}boo[i]${BASH_REMATCH[2]}true${BASH_REMATCH[3]};"

Note that I am using $'stuff' to embed a tab in a string and I use the BASH_REMATCH array to access the parts of the match that I care to reproduce. It's all in the bash man page.

carolflb 11-18-2009 09:42 AM

Hi guys,

first thanks for all replies ;)

I think I didn't express myself the right way. What I wanted to ask with "would you also know how can I tell 'sed' to substitute just the first match?" was that I want to know if it's possible to use 'sed' to erase or substitute just the first occurency of the searched pattern in the file, so if I have:

text
text PATTERN
text
PATTERN
text
PATTERN
text


So, is there a way of substituting the first occurency of PATTERN in the file and erasing the other ones? So that at the end I have:


text
text SUBSTITUTED PATTERN
text
text
text


All times are GMT -5. The time now is 12:34 AM.