Shell *for* 循环遍历文件,并为每一行使用 sed 从其他文件中删除行

Shell *for* 循环遍历文件,并为每一行使用 sed 从其他文件中删除行

long-cluttered-filename.txt我正在尝试通过删除与我的字符串匹配的行来进行清理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

...并且通过一个简单的for循环,我可以迭代该文件的行,如下所示:

$ 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

但当我尝试替代它时,catsed不起作用。这些都不起作用:

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

$l这是变量插值的问题吗?这是for循环的限制吗?

我看到类似的答案循环 sed 从文本文件中删除字符串列表中提供的字符串行从文件中读取行然后删除使用while循环,read但如果可能的话我更愿意使用for循环,如果不可能我想知道为什么。

答案1

如果您有两个文件,其中一个文件包含要从另一个文件中删除的字符串列表,则可以通过一个简单的操作完成整个操作grep

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

long-cluttered-filename.txt这将输出与 中的模式不匹配的所有字符串delete-these-lines.txt

请注意,如果 in 中的某些字符串long-cluttered-filename.txt包含client(例如123superclient456),它仍然匹配client并将从输出中排除。

答案2

切勿使用字母l作为变量名,因为它看起来太像数字1,从而使您的代码变得混乱。正如您已经知道的那样,您想做的是一个坏主意,但是请参阅https://mywiki.wooledge.org/DontReadLinesWithFor了解如何从 shell 中的文件读取行,然后将其编写为:

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

但同样,不要因为已经警告过您的所有原因而这样做(而且您只是重新实现grep -v -f delete-these-lines.txt long-cluttered-filename.txt > tmp && mv tmp long-cluttered-filename.txt效率较低、稳健性较差且可移植性较差)。

相关内容