LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (http://www.linuxquestions.org/questions/programming-9/)
-   -   ?? sed: how to use "1 s/" with -i to replace pattern only once? (http://www.linuxquestions.org/questions/programming-9/sed-how-to-use-1-s-with-i-to-replace-pattern-only-once-778793/)

GrapefruiTgirl 12-29-2009 09:54 PM

?? sed: how to use "1 s/" with -i to replace pattern only once?
 
I think I shouldn't need to be asking this, but I've been frigging around with this and reading sed tutorials for some time now, and I just can't get this to work.

In a text file, I have a bunch of identical lines, like this:


blah..

#STUB
#STUB
#STUB
#STUB
#STUB

more blah..

.. and I want to use sed -i to replace only the FIRST of those #STUB things, with a replacement.
It works in the console, without -i like so:

Code:

bash-3.1# echo "#RULESTUB
#RULESTUB
#RULESTUB
" | sed  "1 s/^#RULESTUB$/replacement/"

outputs:

replacement <--one replacement
#RULESTUB
#RULESTUB

but doing this from within a script, like so:
Code:

sed -i "1 s/^#STUB$/replacement/" $file
does not work. It doesn't replace anything. And if I remove the "1 " it replaces ALL the #STUB lines :confused:

What am I missing?

NOTE: if it matters, the sed operation is double quoted because in the real-world situation, 'replacement' is a $variable.

Sasha

GooseYArd 12-29-2009 10:05 PM

^ and $ are the beginning and end of line anchors. Your search pattern will only match a line that contains exactly "#STUB\n"

GrapefruiTgirl 12-29-2009 10:06 PM

That's *exactly* what the line(s) contains..

GooseYArd 12-29-2009 10:10 PM

in that case, double check your line endings and shell quoting (in case something is eating your end-of-line $), since I just pasted your example into a file here and it works alright.

GrapefruiTgirl 12-29-2009 10:12 PM

Oh!! You may have just got it -- update in a moment...

Nope.. I had thought maybe the $ was being interpreted literally, but it isn't..

FWIW, the replacement operation works fine without the "1 " but it replaces ALL the instances of #STUB, instead of quitting after one replacement. So the regex isn't the problem; in fact, I have an earlier line(s) in the script which use a similar regex, and it works fine (but that earlier line is SUPPOSED to replace ALL instances).

GooseYArd 12-29-2009 10:20 PM

do you mean the first instance in a line, or the first instance in the file?

GrapefruiTgirl 12-29-2009 10:22 PM

First instance in the file. I think I may have identified the problem though.. It may be PEBKAC :rolleyes:

Back in a moment.

GooseYArd 12-29-2009 10:24 PM

ah. make sure your quotes are escaped. I haven't got any idea about replace once per file.

GrapefruiTgirl 12-29-2009 10:28 PM

I'm relieved to NOT have to admit it was PEBKAC :)

But it isn't a quote-escape issue; I use double quotes often for stuff like this, when either the PATTERN or REPLACEMENT is a variable. But still, in this case, I'm stumped. It won't work...

Still trying though!

Thanks for the feedback so far.

Sasha

syg00 12-29-2009 10:38 PM

That "1" is not a match count, it is an address (line number). What's the first line of the file ?.

GrapefruiTgirl 12-29-2009 10:41 PM

@ syg00 -- Aha! So I *AM* doing this wrong after all.

You ask what's the first line of the file? You mean the line's contents? At this moment, the first line reads:

# # THE REAL ONE!

ghostdog74 12-29-2009 11:03 PM

awk
Code:

# more file
#STUB
#STUB
#STUB
#STUB
#STUB

$ awk '{s=(m>=1)?"#STUB":"new";}{m=m+sub("#STUB",s)}1' file
new
#STUB
#STUB
#STUB
#STUB

$ awk '/#STUB/ && !m{sub("#STUB","new");m+=1}m>=1' file
new
#STUB
#STUB
#STUB
#STUB


syg00 12-30-2009 01:31 AM

Conceptually I prefer the latter, however in the case of the target line not being the first line, data will be lost. Slight modification perhaps ?
Code:

awk '/#STUB/ && !m{sub("#STUB","new");m+=1}1' file

ghostdog74 12-30-2009 01:57 AM

Quote:

Originally Posted by syg00 (Post 3808551)
Conceptually I prefer the latter, however in the case of the target line not being the first line, data will be lost.

please give examples, so that i can do the modifications, since the solutions are all done with OP's sample.

syg00 12-30-2009 02:10 AM

As per post #7 from the OP:
Code:

# # THE REAL ONE!
#SLUB
#SLUB
#SLUB
...

Nothing to suggest there isn't more data lines before the required test data.


All times are GMT -5. The time now is 11:59 AM.