Mahsa
Mahsa

Reputation: 207

replacement with sed does not work correctly

I tried following commands and explain my problem:

$cat __sphlist__
signals/APASCI/algi0/algi0.sph
signals/APASCI/ancl0.sph
signals/APASCI/anpe0.sph
signals/APASCI/cepe0.sph

why the following command not working, and show content of signals! :

$cat __sphlist__ | while read f; do sed 's/signals/nb-signals/'  $f; done

but same for echo works?

$cat __sphlist__ | while read f; do echo  $f; done

I changed sed command like below and it works, I wanted to know what is the difference?

$cat __sphlist__ | sed 's/signals/nb-signals/' | while read f; do echo $f ; done

Upvotes: 0

Views: 314

Answers (3)

kvantour
kvantour

Reputation: 26491

First of, the entire command can be replaced by the solution of Kent.

Now to answer your question:

Why the following command not working, and show the content of signals!

cat __sphlist__ | while read f; do sed 's/signals/nb-signals/'  $f; done

This is not a problem with but with your understanding of .

expects to receive a filename as input and will do all its operations on that file. This implies if the variable f has a string which matches a filename (which for the first line equals signals/APASCI/algi0/algi0.sph), will perform its substitution on that file and hence print its content. If $f does not match a file, it will fail.

The command you wrote is equivalent to:

sed 's/signals/nb-signals/' signals/APASCI/algi0/algi0.sph
sed 's/signals/nb-signals/' signals/APASCI/ancl0.sph
sed 's/signals/nb-signals/' signals/APASCI/anpe0.sph
sed 's/signals/nb-signals/' signals/APASCI/cepe0.sph

We do not know what your intentions are, but it looks like you wanted to rename the directory-name signals into nb-signals. Here are several ways to correct your script:

  • Use echo in a pipeline and let read from /dev/stdin

      while read -r f; do echo "$f" | sed 's/signals/nb-signals/'; done < __sphlist__
    
  • Use a here-string as input for

      while read -r f; do sed 's/signals/nb-signals/' <<< "$f"; done < __sphlist__   
    
  • Use bash-substitution

      while read -r f; do echo "${f/signals/nb-signals}"; done < __sphlist__ 
    
  • Just use

      sed 's/signals/nb-signals/' __sphlist__
    

note: Never use cat for looping a file!

Upvotes: 1

Sparrow
Sparrow

Reputation: 148

How SED works.

SED can work with all the lines in a file one by one & hence you don't have to feed SED each line with a WHILE.

$cat sphlist | while read f; do sed 's/signals/nb-signals/' $f; done

In the above, SED sees $f as a file. Since there is no file like that you get "No such file or directory" error.

$cat sphlist | while read f; do echo $f; done

Nothing special in the above command as you're reading line by line & printing them.

$cat sphlist | sed 's/signals/nb-signals/' | while read f; do echo $f ; done

In the above you're passing the CAT result to SED which you could directly do like below

sed 's/signals/nb-signals/' sphlist 

And then you're passing the result of SED to WHILE which prints line by line. The above is only all you need.

sed 's/signals/nb-signals/g' sphlist 

Notice the 'g' in the last of SED in the above command ? that's for a global replacement of values in a file.

Upvotes: 0

Kent
Kent

Reputation: 195189

you should make sed work on file sphlist instead of the lines in that file as input. So:

sed 's/signals/nb-&/' sphlist 

should do.

If you want to change the content of the file, add -i (gnu sed)

Upvotes: 1

Related Questions