This should replace the 1st and the 3rd occurance of "the":
sed -e "s/ the / those /1;s/ the / these /3"
This works only by line.
If there is a second "the", but in an other line for example, it counts it as 1st again and replaces it again.
How can I replace "the" 1st and 3rd occurance globally with sed?
Use Perl:
perl -i.bck -0777 -pe'
s/\bthe\b/++$c==3?those:$c==1?these:$&/ges
' infile
here's a more readable version
awk '{
j=0
for(i=1;i<=NF;i++){
if ($i == "the"){
j++
if (j==1) {
$i = "those"
}else if (j==3){
$i = "these"
}
}
}
print $0
}
' file
ghostdog74:
[...]
[...]
$i = "those"
[...]
Bare in mind that assigning a value to a field will have side effects (FS to OFS).
yes i agree with radoulov on that
awk '/the/{n+=1}{if(n==1||n==3){sub("the","OK",$0)};print}' filename
this looks absolutely beautiful, and it would be nice to work with, but I end up in this error:
+ awk '{ j=0 for(xi=1;xi<=NF;xi++){ if ($xi == "the"){j++ if (j==1) { $xi = "those" }else if (j==3){ $xi = "these" }}}print $0}'
awk: syntax error at source line 1
context is
{ j=0 >>> for <<< (xi=1;xi<=NF;xi++){ if ($xi == "the"){j++ if (j==1) { $xi = "those" }else if (j==3){ $xi = "these" }}}print $0}
awk: illegal statement at source line 1
However, the perl solution works great...
but how can I add a variable similar like this perl/sed mix (which ofcourse does not work this way):
perl -pe' s/\bthe\b/++$c==3?those ${kw2} :$c==1?these ${kw1} :$&/ges '
Thanx a lot!
lowmaster:
this looks absolutely beautiful, and it would be nice to work with, but I end up in this error:
+ awk '{ j=0 for(xi=1;xi<=NF;xi++){ if ($xi == "the"){j++ if (j==1) { $xi = "those" }else if (j==3){ $xi = "these" }}}print $0}'
awk: syntax error at source line 1
context is
{ j=0 >>> for <<< (xi=1;xi<=NF;xi++){ if ($xi == "the"){j++ if (j==1) { $xi = "those" }else if (j==3){ $xi = "these" }}}print $0}
awk: illegal statement at source line 1
why do you want to cramp everything to one line? makes your code ugly to read. Indent your code properly. one liners are cool, but not that cool when you have to troubleshoot your problems.
if you absolutely want to cramp everything to one line, make sure you use appropriate ";".
awk '{ j=0 ; for (...... }'
-----Post Update-----
vidyadhar85:
yes i agree with radoulov on that
awk '/the/{n+=1}{if(n==1&&n==3){sub("the","OK",$0)};print}' filename
i see a logic problem here. n cannot be both equal 1 AND 3 at the same time. therefore your substitution will not work. also i think OP wants to change the "the"s on a line. If there are multiple "the"s on a line, /the/ will only count as 1. Also, what about resetting back n to 0 ?
while i agree with both of you as well about changing the fields, however, in this simple case, its alright.
ghostdog74:
why do you want to cramp everything to one line? makes your code ugly to read. Indent your code properly. one liners are cool, but not that cool when you have to troubleshoot your problems.
if you absolutely want to cramp everything to one line, make sure you use appropriate ";".
awk '{ j=0 ; for (...... }'
-----Post Update-----
i see a logic problem here. n cannot be both equal 1 AND 3 at the same time. therefore your substitution will not work. Also, what about resetting back n to 0 ?
while i agree with both of you as well about changing the fields, however, in this simple case, its alright.
... I know I know. I need a quick solution for a problem and did not digg deeper into all those fantastic sed/awk/perl stuff...
you are absolutely right, oneliners are very very bad for reading.
You should see my code... nearly all pocessing is done in one line, a lynx output piped again and again... kilometers long.
And the more readable version of it made me even understand what this onliners really are...
Now this AWK solution of ghostdog74 works allmost perfect, if I put the ; to the right places, but
I need this to count the "the"s of all lines, this solution seems to count and replace only per line, like my simple sed example at the beginning...
Thanx alot!
i see a logic problem here. n cannot be both equal 1 AND 3 at the same time. therefore your substitution will not work. also i think OP wants to change the "the"s on a line. If there are multiple "the"s on a line, /the/ will only count as 1. Also, what about resetting back n to 0 ?
while i agree with both of you as well about changing the fields, however, in this simple case, its alright.
Sorry I did a typing mistake its not && it should be ||
thanks for pointing it out
ah...so its not on each line, but one all lines .... my bad.
[...]
However, the perl solution works great...
but how can I add a variable similar like this perl/sed mix (which ofcourse does not work this way):
[...]
perl -i.bck -0777 -pe'BEGIN {
( $v1, $v2 ) = ( $ENV{kw1}, $ENV{kw2} );
}
s/\bthe\b/
++$c == 3 ?
"those $v2 " :
$c == 1 ?
"these $v1 " :
$&
/xges
' infile
Thanx for this, but my $v1, $v2 stays empty for some reason. What have I to do to to move the content of kw1 to v1?
part1=$(perl -e 'srand; rand($.) < 1 && ($line = $_) while <>; print $line;' /text/part1.TXT)
part2=$(perl -e 'srand; rand($.) < 1 && ($line = $_) while <>; print $line;' /text/part2.TXT)
part3=$(perl -e 'srand; rand($.) < 1 && ($line = $_) while <>; print $line;' /text/part3.TXT)
part4=$(perl -e 'srand; rand($.) < 1 && ($line = $_) while <>; print $line;' /text/part4.TXT)
part5=$(perl -e 'srand; rand($.) < 1 && ($line = $_) while <>; print $line;' /text/part5.TXT)
part6=$(perl -e 'srand; rand($.) < 1 && ($line = $_) while <>; print $line;' /text/part1.TXT)
part7=$(perl -e 'srand; rand($.) < 1 && ($line = $_) while <>; print $line;' /text/part1.TXT)
part9=$(perl -e 'srand; rand($.) < 1 && ($line = $_) while <>; print $line;' /text/part1.TXT)
part8=$(perl -e 'srand; rand($.) < 1 && ($line = $_) while <>; print $line;' /text/part4.TXT)
...
kw1=`echo "$kwt $part9 $kwt $part2 - $kwt - $part6 | $kwt $part8 - $kwt"`
...
...
perl -i.bck -0777 -pe'BEGIN {
( $v1, $v2 ) = ( $ENV{kw1}, $ENV{kw2} );
}
s/\bthe\b/
++$c == 3 ?
"those $v2 " :
$c == 1 ?
"these $v1 " :
$&
/xges
' infile
You need to export them:
kw1=...
kw2=...
export kw1 kw2
Here is my sed one-liner for this problem:
sed -n '1h;1!H;${x;s/the/those/1;s/the/these/2;p}' input_file
Basically, what it does is to accumulate the whole file in the hold buffer ( 1h;1!H ) and then when sed reaches the end of the file ($) it copies the content of the hold buffer back to the pattern buffer where the replacements take place.
However, i would not recommend using this solution with large files, because it can be memory-consuming (the whole file will be buffered, instead of the usual one line)