0

I'm trying to clean up long-cluttered-filename.txt by deleting the lines that match the strings in my delete-these-lines.txt...

$ cat delete-these-lines.txt
context
platform
server
civicrm
site_enabled
client
redirection
cron_key
^\s*[0-9]*\s
alias
profile
install
ssl_
address

...and with a simple for loop I can iterate through the lines of that file like so:

$ for l in delete-these-lines.txt; do cat $l; done
context
platform
server
civicrm
site_enabled
client
redirection
cron_key
^\s*[0-9]*\s
alias
profile
install
ssl_
address

but when I try to substitute cat for sed it doesn't work. Neither of these work:

for l in delete-these-lines.txt; do sed -i "/$l/d" long-cluttered-filename.txt; done
for l in delete-these-lines.txt; do sed -i '/"$l"/d' long-cluttered-filename.txt; done

Is this a problem with the $l variable being interpolated? Is this a limitation of for loops?

I see answers like loop sed to delete line with strings provided in a list of strings from a text file and Read line from file then delete that use while loops with read but I'd prefer to use a for loop if it's possible, and if it's not possible I'd like to know why.

Paulo Tomé
  • 3,782
alec
  • 1,708

2 Answers2

1

If you have two files where one contains list of strings to delete from another one, you can do the entire thing with one simple grep:

grep -v -f delete-these-lines.txt long-cluttered-filename.txt

This will output all the strings from long-cluttered-filename.txt which do not match to patterns from delete-these-lines.txt.

Note, that in case some string in long-cluttered-filename.txt will contain client (e.g. 123superclient456) it still matches to client and will be excluded from the output.

rush
  • 27,403
1

Never use the letter l as a variable name as it looks far too much like the number 1 and so obfuscates your code. What you want to do is a bad idea as you already know, but see https://mywiki.wooledge.org/DontReadLinesWithFor for how to read lines from a file in shell and then you'd write it as:

while IFS= read -r regexp; do
    sed -i "/$regexp/d" long-cluttered-filename.txt
done < delete-these-lines.txt

but again - don't do it for all the reasons you've already been warned of (plus you're just re-implementing grep -v -f delete-these-lines.txt long-cluttered-filename.txt > tmp && mv tmp long-cluttered-filename.txt less efficiently, less robustly, and less portably).

Ed Morton
  • 31,617