user1988385
user1988385

Reputation: 2869

Linux sed command does not change the target file

With my shell script, when I run ./Test1 hello result.

It is supposed to take hello as standard input and result as standard output. The shell should remove any whitespace before <td>, </td>, and abc

So, I write the script this way

tr -d [:blank:] < $1
grep -r "<td>" $1 | sed -r 's/<td>//g' > $2
sed -r 's/<\/td>//g' $2
sed -r 's/abc//g' $2

However, when I run this command, the content of result file is exactly the same as the content of hello file (the only difference is the whitespace is removed)

The file hello content:

<td>hello</td>
  <td>hello</td>
    <td>hello</td>
<td>abc</td>
 <td>abc</td>

How do I get sed to apply the change to the target file?

Upvotes: 11

Views: 15977

Answers (6)

Aviv
Aviv

Reputation: 14537

In sed command Use the -i option in order to change file itself, if not, the output printed on the screen but the file stays the same.

The formula would be:

sed -i <targetFile> 's/<beforeText>/<afterText>/g' <targetFile>

For example:

sed -i myCredentials.txt 's/secretPassword/xxx/g' myCredentials.txt

Another option - output to another file and rename it:

sed 's/secretPassword/xxx/g' myCredentials.txt > temp.txt
rm myCredentials.txt && mv temp.txt myCredentials.txt

for more info, look at the documentation:

The sed utility reads the specified files, or the standard input if no files are specified, modifying the input as specified by a list of com- mands. The input is then written to the standard output. A single command may be specified as the first argument to sed. Multiple commands may be specified by using the -e or -f options. All commands are applied to the input in the order they are specified regardless of their origin.

-i Edit files in-place, saving backups with the specified extension. If a zero-length extension is given, no backup will be saved. It is not recommended to give a zero-length extension when in-place editing files, as you risk corruption or partial content in situ- ations where disk space is exhausted, etc.

Upvotes: 5

Ed Morton
Ed Morton

Reputation: 204648

All you need is 1 simple sed or awk substitution line:

sed -r 's/[[:blank:]]|<\/?td>|abc//g' file
awk '{gsub(/[[:blank:]]|<\/?td>|abc/,"")}1' file

e.g.:

$ cat file
<td>hello</td>
  <td>hello</td>
    <td>hello</td>
<td>abc</td>
 <td>abc</td>

$ sed -r 's/[[:blank:]]|<\/?td>|abc//g' file
hello
hello
hello

Upvotes: 0

Chris Seymour
Chris Seymour

Reputation: 85883

If you want to store the changes from sed back to the file use the -i option:

$ cat file
<head>abc</head>
    <td>hello</td>
      <td>hello</td>
        <td>hello</td>
    <td>abc</td>
     <td>abc</td>
<h1>abc</h1>

$ sed -ni '/<td>/{s/^\s*//;s/abc//;s/<\/\?td>//g;p}' file

$ cat file
hello
hello
hello

Edit: The regexp is clearer if we use a different separator with sed and use the extended regexp option -r:

$ sed -r 's_</?td>__g' file
    hello
      hello
        hello
    abc
     abc

The ? make the previous character optional so the / doesn't have to be present making the regexp match <td> and </td> in one.

Upvotes: 10

Kent
Kent

Reputation: 195269

grep solution:

kent$  echo "<td>hello</td>
  <td>hello</td>
    <td>hello</td>
<td>abc</td>
 <td>abc</td>"|grep -v 'abc'|grep -oP '(?<=<td>).*(?=</td>)'                                                                                                                
hello
hello
hello

awk solution:

kent$  echo "<td>hello</td>
  <td>hello</td>
    <td>hello</td>
<td>abc</td>
 <td>abc</td>"|awk -F"</?td>" '!/abc/{print $2}'
hello
hello
hello

Upvotes: 0

Slartibartfast
Slartibartfast

Reputation: 1623

If you want sed to modify a file you need to pass -e

Upvotes: -2

Anton Kovalenko
Anton Kovalenko

Reputation: 21517

If you want sed to edit an existing file in place, you should give -i option to it.

UPD: and it's not clear what you want to do with the result of tr (now it goes to the script's standard output, is it intended?)

Upvotes: 1

Related Questions