1

I have a file that has two columns like such.

cat test.txt

100 2007
FFF 1993
7E7 1994
4BB 1995

I need to input each of the lines into a script, and have the two columns assigned as separate variables so I can run them through a different loop, and then move onto the next line.

I have a long list of files that I need to perform a find and replace function for each of the pairs. I am converting sets to year which I already have mapped out.

My script will look something like this.

SET=$1
YEAR=$2

for i in `ls` ; do
sed -i "" 's/"$1"/"$2"/g' $i;
done

I cant figure out how to have the test.txt loop the script with the new lines.

3

You can use read to split the lines based on whitespace (which it looks like your file uses). Something like this:

while read set year; do
    DoStuffWith "$set" "$year"
done <test.txt

Other notes:

  • Note that I used lowercase variable names in the above example. There are a bunch of all-caps names with special meanings, and the safest way to avoid conflicts with them is to stick to lower- or mixed-case variables (unless you want the special meaning).

  • Don't iterate over the output of ls, just use for i in *; do. And double-quote the reference to $i to avoid weird parsing in some cases.

    Except you don't need to do that, sed can iterate over files all by itself if you use sed -i "" 'whatever' *.

  • In the sed command, it looks like you're trying to use variable substitutions and double-quotes inside single-quoted strings, and that doesn't work. If you don't want the double-quotes to be literally part of the search/replace strings, use this instead:

    sed -i "" "s/$set/$year/g" *
    

    If you do want literal double-quotes in the search and replace strings, escape them:

    sed -i "" "s/\"$set\"/\"$year\"/g" *
    
  • It looks like you're planning to loop through the file, and for each line loop over every file replacing that one string. Why not have a single run do all the replacements? That is, rather than running sed with the command s/100/2007/g, and then again with s/FFF/1993/g, and then again... why not run it just once with the command s/100/2007/g; s/FFF/1993/g; s/7E7/1994/g; ...?

    You'd need to build the sed command in a loop, something like this:

    sedCommand=""
    while read set year; do
        sedCommand+="s/$set/$year/g; "
    done <test.txt
    
    sed -i "" "$sedCommand" *
    
  • Finally, global replacements like this worry me. Are you sure that "100" doesn't occur in any file except those instances where it should be replaced by "2007"? Does that include the test.txt file?

    Do you have a backup of all of these files? You really should before turning something like this loose on anything you don't want to lose.

| improve this answer | |
  • 1
    +1 ... a related approach that avoids the shell loop might be something like xargs -L1 printf 's/%s/%s/g\n' < test.txt | sed -i "" -f- -- * – steeldriver Jul 10 '19 at 1:46
  • very thorough answer. – glenn jackman Jul 10 '19 at 2:12
  • This was my first question on here. You might have set the bar too high for answers I should expect back haha. Thanks, it worked great! – maclian Jul 10 '19 at 15:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.