LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Call each line in a file as an argument to another command in Bash (https://www.linuxquestions.org/questions/linux-newbie-8/call-each-line-in-a-file-as-an-argument-to-another-command-in-bash-4175584949/)

pradeepspa 07-18-2016 08:47 AM

Call each line in a file as an argument to another command in Bash
 
Hi All,

I am new to bash script so please done mind if my question is trivial.

I am trying to build a script where I need to call each line of a file , use it as input to sed and generate output. This should follow for rest of the lines as well.

I was using the below one but doesnt seems to be working. Could someone give me a hand in debugging this or provide anyother solution ?


old="hi"
new="bye"
while I= read -r a; do
sed -i -e "/^$a/s/$old/$new/" /tmp/test.txt
done </tmp/tacfile.txt

keefaz 07-18-2016 09:04 AM

Not sure what the I= is for, but you'll need a space after /^$a/, before s/$old/$new/

[edit]
No it seems to work as this (without the space)
It won't generate output with the -i option (edit file in place)

HMW 07-18-2016 09:33 AM

Hi!

Please use code tags when posting code, it makes for much easier reading.

It seems to me that you are complicating things. Given this infile:
Code:

hi foo
bye bar
hi foobar

I would use this little thing:
Code:

#!/bin/bash

old="hi"
new="bye"

while read -r line; do
    echo $line | sed "s/$old/$new/"
done < in.txt

exit 0

Or even a straight sed from the command line, like this:
Code:

sed 's/hi/bye/g' in.txt
bye foo
bye bar
bye foobar

Best regards,
HMW

grail 07-18-2016 10:33 AM

Quote:

I was using the below one but doesnt seems to be working.
Please don't use simple terms ike this as there is nothing to be gleaned from this information. Instead explain 'what is not working' or 'why YOU think it doesn't work'.

And as shown by HMW, provide some input, actual output and expected output, plus any error messages if any.

Also, in future, please use [code][/code] tags around code / data so it is more legible and maintains formatting.

pan64 07-18-2016 11:39 AM

Quote:

Originally Posted by HMW (Post 5577804)
Code:

while read -r line; do
    echo $line | sed "s/$old/$new/"
done < in.txt

exit 0

HMW

I'm really sorry, but I do not like that kind of "solutions"
I mean you created an unnecessary loop, therefore you have now loop (of sed) inside loop (of while).
That is very, very ineffective, this is something called "bad practice".
A much better solution would be (yes, I know you know it, so just to repeat):
Code:

sed "s/$old/$new/" in.txt

HMW 07-18-2016 12:27 PM

Quote:

Originally Posted by pan64 (Post 5577854)
I'm really sorry, but I do not like that kind of "solutions"

No need to be sorry, I agree completely. I just modified OP's original attempt so it at least works!
Quote:

Originally Posted by pan64 (Post 5577854)
A much better solution would be (yes, I know you know it, so just to repeat):
Code:

sed "s/$old/$new/" in.txt

Yep!

keefaz 07-18-2016 01:56 PM

Not sure I follow well but
Code:

sed "s/$old/$new/" in.txt
Is not exactly what OP required with
Code:

sed "/^$a/s/$old/$new/" in.txt
Replace $old with $new if /^something else/

pradeepspa 07-18-2016 02:13 PM

Guys Thanks a lot for the response. I should have been more clear in my point. Sorry about that.

The reason why I use sed is not to change the sting directly.

Example.
In file test.txt,

hi My name is Pradeep
bye My name is Pradeep

sed -i -e "/^hi/s/Pradeep/spa/"

So wherever i find "hi" as first occurance of a line, I need to change "Pradeep" to "Spa". Here "Hi" is not static where I have list of variables which i need to call from a file /tmp/tacfile.txt.

keefaz 07-18-2016 04:44 PM

So your script works :)

pradeepspa 07-18-2016 04:50 PM

Not exactly. For some reason its changing all instance regardless of my condition (hi or bye)

pradeepspa 07-18-2016 05:14 PM

could someone know why its not filtering properly. Usage of sed is not proper or anything? I ran manually where it works. Only as a whole file its not

keefaz 07-18-2016 05:25 PM

Maybe remove -i option and redirect output to a temp file then move temp file to test.txt

edit:
wrong approach, I was thinking of capturing output from loop but the test.txt content will repeat after each loop iteration.

I would be curious to see test.txt and tacfile.txt content though

Another idea would be to build match pattern from tacfile.txt
something like: ^something|^thing|^this|^that

Code:

old="hi"
new="bye"

a=$(sed 's/.*/^&/' /tmp/tacfile.txt | paste -s -d'|' -)

sed -r -i -e "/$a/s/$old/$new/" /tmp/test.txt


pradeepspa 07-18-2016 05:54 PM

changed the condition to " sed -i -e "/$a/ s/$old/$new/ ; /$a/! s/$old/$old/" which did the work.

Thanks all for helping

grail 07-18-2016 11:08 PM

Well that makes little sense as to why you would need to go that way. Are you sure the file(s) being edited aren't originally Windows files? The dodgy line endings could be messing up sed.

pradeepspa 07-19-2016 11:31 AM

They are not windows file. Just a text file on linux.


All times are GMT -5. The time now is 02:54 PM.