开发者

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}"
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜