first replacement of a string in a file using sed
I would like to know how can I replace the first occurrence of searched pattern in the entire file.For example,
import java.io.File;
import java.io.File;
should be replaced by
import java.io.IOException;
import java.io.File;
How do I achieve th开发者_运维问答is using sed ? Thank You
There’s certainly no need to write some big long script when it only takes on substitution to do all the work in one line. You just have to pick the right Power Tool for the job.
Here’s a Perl one-liner:
% cat -n /tmp/f
1 import java.lang.Character;
2 import java.io.File;
3 import java.io.File;
4 import java.util.Pattern;
% perl -pe 's//IoException/ if m?import java\.io\.\KFile?' /tmp/f
import java.lang.Character;
import java.io.IoException;
import java.io.File;
import java.util.Pattern;
And if you want to do it with an edit of the file, just add -i.bak:
% perl -i.bak -pe 's//IoException/ if m?import java\.io\.\KFile?' /tmp/f
% head /tmp/f{,.bak}
==> /tmp/f <==
import java.lang.Character;
import java.io.IoException;
import java.io.File;
import java.util.Pattern;
==> /tmp/f.bak <==
import java.lang.Character;
import java.io.File;
import java.io.File;
import java.util.Pattern;
The reason that works is because when you give the m//
operator a ??
delimiter, it has some built-in state to remember to match the first time only.
Then in the substitute, the empty pattern means to reuse the last matched pattern, so you don’t have to type it again and risk the two ever divering.
Finally, the \K
in the pattern reneges on the match, “keeping” the stuff to the left, so that it doesn’t get gobbled by the substitute.
cat file | sed -e ':l
0,/my_search_str/ {
/my_search_str/! {
N;
b l
}
s/my_search_str/replace_this/g
:t
N
b t
}
'
this is working for me: file: (before)
hello1
my_search_str
hello2
mysearch_str
hello3
file:(after)
hello1
replace_this
hello2
mysearch_str
hello3
What I would do is to append all the lines in a great line and replace the content.
$ cat f
import java.io.File;
import java.io.File;
$ sed -n 'N
${
s/import java.io.File;/import java.io.IOException/
p
}' f
import java.io.IOException
import java.io.File;
How it works: first, I suppress the line printing, which is the default behavior, passing the -n
option to sed.
Then there comes the sed commmands. The first one is the N
command: it appends a newline and the next line of the stream to the current one, maintaining then at the pattern space. This will change the current line to the next one, and then the next line will be appended... until the end of the file.
At the end of the file and after the N
command to be executed at the last line as well, the pattern space will contain all the lines. Then, at the end of the file (which is specified by the $
address) we just replace the desired line with:
s/import java.io.File;/import java.io.IOException/
Since the s///
command does only one replacement per iteration at the pattern space by default, it will only replace the first line. Now the pattern space has the line replaced, but will not be printed out since we used the -n
option. So, we need to print it with the p
command. Once we will execute two operations at the end of the file, we adress it with $
and put the operations between brackets ({}
).
There, we just presented the sed commands in more than one line for clarity. We can use them all in one line; just separate them by semicolons:
$ sed -n 'N;${s/import java.io.File;/import java.io.IOException/;p;}' f
import java.io.IOException
import java.io.File;
HTH
Just do it on the command line as below:
cat text.txt |
awk '/File/{
if ( count < 1 ){ gsub("File","IOException")}
count++
print
}'
you can use a shell script (Bash)
#!/bin/bash
declare -i toggle=0
while read -r line
do
case "$line" in
*import*java.io.File*)
if [ $toggle -eq 1 ];then
echo "$line"
continue
fi
echo "import java.io.Exception";
toggle=1
continue
;;
esac
echo "$line"
done < file
Sample output
$> more file
import java.util.Scanner;
import java.io.File;
import java.io.File;
$> bash search_replace.sh
import java.util.Scanner;
import java.io.Exception
import java.io.File;
Or you can slurp the whole file into memory and do a one time substitution
data=$(<file)
echo "${data/import java.io.File;/import java.io.IOException}"
精彩评论