Sumary
GNU syntax:
sed '/claudio/{s//claudia/;:p;n;bp}' file
Or even (to use only one time the word to be replaced:
sed '/\(claudi\)o/{s//\1a/;:p;n;bp}' file
Or, in POSIX syntax:
sed -e '/claudio/{s//claudia/;:p' -e 'n;bp' -e '}' file
works on any sed, process only as many lines as needed to find the first claudio
, works even if claudio
is in the first line and is shorter as it use only one regex string.
Detail
To change only one line you need to select only one line.
Using a 1,/claudio/
(from your question) selects:
- from the first line (unconditionally)
- to the next line that contains the string
claudio
.
$ cat file
claudio 1
antonio 2
claudio 3
michele 4
$ sed -n '1,/claudio/{p}' file
claudio 1
antonio 2
claudio 3
To select any line that contains claudio
, use:
$ sed -n `/claudio/{p}` file
claudio 1
claudio 3
And to select only the first claudio
in the file, use:
sed -n '/claudio/{p;q}' file
claudio 1
Then, you can make a substitution on that line only:
sed '/claudio/{s/claudio/claudia/;q}' file
claudia 1
Which will change only the first occurrence of the regex match on the line, even if there may be more than one, on the first line that match the regex.
Of course, the /claudio/
regex could be simplified to:
$ sed '/claudio/{s//claudia/;q}' file
claudia 1
And, then, the only thing missing is to print all other lines un-modified:
sed '/claudio/{s//claudia/;:p;n;bp}' file
info sed
: (0,/REGEXP/
: A line number of 0 can be used in an address specification like0,/REGEXP/
so thatsed
will try to match REGEXP in the first input line too. In other words,0,/REGEXP/
is similar to1,/REGEXP/
, except that if ADDR2 matches the very first line of input the 0,/REGEXP/ form will consider it to end the range, whereas the 1,/REGEXP/ form will match the beginning of its range and hence make the range span up to the second occurrence of the regular expression)awk '/claudio/ && !ok { sub(/claudio/,"claudia"); ok=1 } 1' nomi
should do