Linux 如何删除与数组中共享的字符串匹配的行
我有一个由如下文本组成的文件Linux 如何删除与数组中共享的字符串匹配的行,linux,bash,Linux,Bash,我有一个由如下文本组成的文件 compile_tool/opt/CSDTK/bin/chipgen/Modem2G/toolpool/plugins/Calib/libcalibplugin.so compile_tool/opt/CSDTK/bin/chipgen/Modem2G/toolpool/plugins/Calib/libcalibplugin.dill compile_tool/opt/CSDTK/bin/lib/ruby/gems/1.8/gems/builder-2.1.2/R
compile_tool/opt/CSDTK/bin/chipgen/Modem2G/toolpool/plugins/Calib/libcalibplugin.so
compile_tool/opt/CSDTK/bin/chipgen/Modem2G/toolpool/plugins/Calib/libcalibplugin.dill
compile_tool/opt/CSDTK/bin/lib/ruby/gems/1.8/gems/builder-2.1.2/Rakefile.pg
compile_tool/opt/mingw32_3.4.4/usr/i586-mingw32msvc/include/mmsystem.c
compile_tool/opt/mingw32_3.4.4/usr/i586-mingw32msvc/include/winnt.h
compile_tool/opt/CSDTK/bin/lib/ruby/gems/1.8/gems/builder-2.1.2/test/test_xchar.HEX
我想删除文件扩展名为.so、.dill、.pg和.HEX的行。我试过下面的代码,但没有成功
#! /bin/bash
array=(.a .so .bin.ihex .dll .exe .gem .bin .png .HEX)
for a in "${array[@]}"
do
sed -i -e "/\$a\b/d" copyright
done
不必为每个扩展调用一次sed,您可以使用以下方法:
IFS=$'\n'
grep -F -v "${array[*]}" copyright
如果其输出看起来不错,请将其重定向到一个文件,并将其名称更改为copyright,必要时恢复IFS。您可以使用以下方法,而不是为每个扩展名调用一次sed:
IFS=$'\n'
grep -F -v "${array[*]}" copyright
如果其输出看起来不错,请将其重定向到一个文件,并将其名称更改为版权,必要时恢复IFS。如果您的sed支持正则表达式中的\|或运算符,请尝试:
array=(.a .so .bin.ihex .dll .exe .gem .bin .png .HEX)
pat="$(IFS='|'; echo "${array[*]}" | sed -e 's/|/\\|/g' -e 's/\./\\./g')"
sed "/\($pat\)\$/d" copyright
它连接数组元素并生成一个模式字符串,看起来像:\.a\\\\.so\\.bin\.ihex\\\\。。。。
然后sed/\$pat\\$/d行文本删除与模式匹配的行。
请注意,您的数组元素和具有文件扩展名.so、.dill、.pg和.HEX的文本行可能不一致。我已按原样使用了您的数组。如果您的sed支持正则表达式中的\| or运算符,请尝试:
array=(.a .so .bin.ihex .dll .exe .gem .bin .png .HEX)
pat="$(IFS='|'; echo "${array[*]}" | sed -e 's/|/\\|/g' -e 's/\./\\./g')"
sed "/\($pat\)\$/d" copyright
它连接数组元素并生成一个模式字符串,看起来像:\.a\\\\.so\\.bin\.ihex\\\\。。。。
然后sed/\$pat\\$/d行文本删除与模式匹配的行。
请注意,您的数组元素和具有文件扩展名.so、.dill、.pg和.HEX的文本行可能不一致。我已经按原样使用了您的阵列。根据Oguz Ismail的回答,从与他讨论的想法开始: 无论您是使用grep-e还是sed来标识保存的文件,问题是在这两种情况下,数组的元素都被解释为正则表达式。例如,您有一个数组元素.a,作为regexp,这意味着它将匹配任何包含字母“a”的文件,但文件名开头除外。因此,main.c行也将与pattern.a匹配 一种可能性是使用通配符匹配而不是regexp匹配,但这意味着您需要显式循环数组:例如,要测试$line行是否将被删除或应保留,您必须执行以下操作:
line_matches_pat=no
for pat in "${array[@]}"
do
if [[ $line == *$pat ]]
then
line_matches_pat=yes
break
fi
done
如果$line_matches_pat等于yes,则该行与数组中的一个模式匹配
在我看来,更明智、更灵活的方法是在数组中存储您感兴趣的文件的正则表达式,而不是文件的扩展名。这使您有一天可以在列表中输入类似于包含字符串error_uu并具有扩展名.c的文件名的内容。当您这样做时,您可以使用类似于@oguzismail建议的解决方案的方法,但是您当然不能再将-F与grep一起使用了:
grep -E -v "${array[*]}" copyright
这将打开扩展正则表达式。如果你对简单的正则表达式没问题,请删除-E。从Oguz Ismail根据他的答案讨论的想法开始: 无论您是使用grep-e还是sed来标识保存的文件,问题是在这两种情况下,数组的元素都被解释为正则表达式。例如,您有一个数组元素.a,作为regexp,这意味着它将匹配任何包含字母“a”的文件,但文件名开头除外。因此,main.c行也将与pattern.a匹配 一种可能性是使用通配符匹配而不是regexp匹配,但这意味着您需要显式循环数组:例如,要测试$line行是否将被删除或应保留,您必须执行以下操作:
line_matches_pat=no
for pat in "${array[@]}"
do
if [[ $line == *$pat ]]
then
line_matches_pat=yes
break
fi
done
如果$line_matches_pat等于yes,则该行与数组中的一个模式匹配
在我看来,更明智、更灵活的方法是在数组中存储您感兴趣的文件的正则表达式,而不是文件的扩展名。这使您有一天可以在列表中输入类似于包含字符串error_uu并具有扩展名.c的文件名的内容。当您这样做时,您可以使用类似于@oguzismail建议的解决方案的方法,但是您当然不能再将-F与grep一起使用了:
grep -E -v "${array[*]}" copyright
这将打开扩展正则表达式。如果你对简单的正则表达式没问题,请删除-E。与@tshiono建议的相同,但使用printf构建模式
printf -v pat '\%s\|' ${array[@]}
sed "/${pat%*'\|'}/d" copyright
与@tshiono建议的相同,但使用printf构建模式
printf -v pat '\%s\|' ${array[@]}
sed "/${pat%*'\|'}/d" copyright
@oguzismail:这也会删除一行,比如abc.sox.txt。数组中的扩展名需要在文件名的末尾匹配。也许我们必须首先转换数组,在末尾添加$,然后从grep中省略-F。@user1934428是的,我只是假设OP的输入中没有这样的行。为了涵盖这些情况,以及在元素中添加$,我们也需要逃逸;否则的话,比如说$也会和abc.iso匹配,你是对的。也许是一个更明智的选择,最终也更明智
灵活的方法是让files.txt包含egrep模式,而不是文件名。@oguzismail:这也会删除一行,比如abc.sox.txt。数组中的扩展名需要在文件名的末尾匹配。也许我们必须首先转换数组,在末尾添加$,然后从grep中省略-F。@user1934428是的,我只是假设OP的输入中没有这样的行。为了涵盖这些情况,以及在元素中添加$,我们也需要逃逸;否则的话,比如说$也会和abc.iso匹配,你是对的。也许一种更明智、更灵活的方法是让files.txt包含egrep模式,而不是文件名。