Reputation: 109
I would like to write a script with sed
command as I guess this is most suitable command for my goal.
There is a file called NAME
which consists of different names ordered in columns like:
STEVE
JOHN
CLARE
The script should do:
$value
from NAME
file$value
with the constant value ('ARNOLD') by sed 's/"'$i'"/ARNOLD/g' test1.log>test2.log
(test1 and test2 files are identical).I prepared my version of script but it worked only for the latest value in the list of names:
while read i; do sed 's/'"$i"'/ARNOLD/g' test1.log >test2.log ; done<name
Upvotes: 0
Views: 2484
Reputation: 20002
When you made a copy from your original test1.log, you can overwrite test1.log.
You could use sed -i
or
sed 's/'"$i"'/ARNOLD/g' test1.log >test2.log && mv test2.log test1.log
This solution requires a lot of I/O and is worse than @Ed's solution. I just added it to show how the problem @msw noticed could be fixed.
Upvotes: 0
Reputation: 203502
Something like this might be what you need:
awk 'NR==FNR{names[$0];next} {for (name in names) gsub(name,"ARNOLD")}' NAME test1.log >test2.log
but without sample input and expected output it's a guess and it has the same potential problem with non-anchoring that all of the sed scripts posted so far have in that it'd, for example, change "JOHNSON" to "ARNOLDSON". WIth GNU awk you can solve that with word boundaries:
awk 'NR==FNR{names[$0];next} {for (name in names) gsub("\\<"name"\\>","ARNOLD")}' NAME test1.log >test2.log
but there may be other issues that we won't know be able to help you with until we see your sample input and expected output.
wrt using awk vs shell+sed (moved from a comment):
Every time you write a shell loop just to manipulate text you have the wrong approach. See https://unix.stackexchange.com/q/169716 for one discussion on the subject. Essentially though - UNIX shell is an environment from which to call UNIX tools with a language to sequence those calls. Awk is the tool created by the same guys who invented shell to do text processing for UNIX. So, just use it. In shell you can write scripts that LOOK like they'll do the job but it's actually incredibly difficult to get the shell syntax right to robustly do text manipulation since that's not what it's designed to do (eg. while read i
is NOT how to read input in shell - you need while IFS= read -r i
at least) and even if you manage to get the syntax right it's immensely slow compared to awk.
If you're going to be doing ANY text manipulation in UNIX you should get the book Effective Awk Programming, 4th Edition, by Arnold Robbins or you're going to be wasting a lot of time creating complicated, inefficient, buggy, unmaintainable and otherwise generally awful shell scripts.
Upvotes: 2
Reputation: 11216
You can use sed to generate the changes and then use the output from the first as a script for another sed to read
sed 's/.*/s\/&\/ARNOLD\/g/' NAME | sed -f- test1.log >test2.log
sed 's/.*/s\/&\/ARNOLD\/g/'
Creates
s/STEVE/ARNOLD/g
s/JOHN/ARNOLD/g
s/CLARE/ARNOLD/g
which is then piped to
sed -f-
-f
reads a script file
-
is standard in from the pipe
Upvotes: 1
Reputation: 43487
Every time your script loops, it starts with the unmodified test1.log
and changes one name. That means that only the last name changed will appear in test2.log
.
Each loop un-does all prior changes.
Upvotes: 0