删除文件中匹配一个字符串但不匹配另一个字符串的行 - SED,BASH?

时间:2022-01-12 04:39:49

I want to remove all lines in a file which contain the word "test" but if that line contains "test@" then I do not want to delete it.

我想删除包含单词“test”的文件中的所有行,但如果该行包含“test @”,那么我不想删除它。

There is probably some funky way of doing this with sed but I am struggling, I tried to write a bash loop using sed but this is probably stupid.

可能有一些时髦的方式用sed这样做,但我很挣扎,我试着用sed写一个bash循环,但这可能是愚蠢的。

filetest=/tmp/filetest
filetest_tmp=/tmp/filetest.tmp<
line_num=0

while read line; do
        line_num=$(($line_num+1))
        if [[ $line == *rootsh* ]] && [[ $line != *root@* ]]
                then
                sed -e "${line_num}"'d' $filetest >> $filetest_tmp
        fi
done < $filetest
cp $syslog_tmp $filetest

As you can tell, I'm a newb at this :(

你可以告诉我,我是一个新手:(

4 个解决方案

#1


10  

sed -e '/test/{/test@/!d;}'

The first pattern matches the lines containing 'test'; the second pattern deletes lines unless they match 'test@'.

第一个模式匹配包含'test'的行;第二种模式删除行,除非它们匹配'test @'。

Tested on the data file:

测试数据文件:

aaaa
bbbtestbbb
ccctest@ccc
test!
dddd

Output:

aaaa
ccctest@ccc
dddd

That seems to meet your requirements.

这似乎符合您的要求。

#2


4  

Use grep:

grep -v 'test[^@]' infile

Usually grep prints matching lines but -v tells it to print non-matching lines.

通常grep打印匹配的行,但-v告诉它打印不匹配的行。

The regular expression matches any occurance of "test" that is followed by anything but a '@'. This is fine if you don't have to expect "test" coming up at the end of a line. If that is the case, use

正则表达式匹配任何“test”的出现,后面除了“@”之外的任何东西。如果您不必期望在一行结束时出现“测试”,那么这很好。如果是这种情况,请使用

grep -E -v 'test([^@]|$)'

I don't think it is worth going into why your solution does not work, because it is broken in so many ways.

我不认为值得讨论为什么你的解决方案不起作用,因为它在很多方面被打破了。

#3


1  

If you flip your question around a bit, it becomes:

如果你翻一下你的问题,它会变成:

How do I filter out all lines from a file that either contains the string 'test@' or does not contain the string 'test'.

如何过滤掉包含字符串'test @'或不包含字符串'test'的文件中的所有行。

This can for example be done in awk like this:

例如,这可以在awk中完成,如下所示:

awk '!/foo/ || /foo@/' testfile

Jonathan's answer also works, I just wanted to give you an alternate version.

Jonathan的回答也有效,我只是想给你一个替代版本。

#4


1  

There is no need for a tmp file if you use ed!

如果使用ed,则不需要tmp文件!

# cf. http://wiki.bash-hackers.org/howto/edit-ed
cat <<-'EOF' | ed -s file
H
,g/test$/d
,g/test[^@]/d
wq
EOF

#1


10  

sed -e '/test/{/test@/!d;}'

The first pattern matches the lines containing 'test'; the second pattern deletes lines unless they match 'test@'.

第一个模式匹配包含'test'的行;第二种模式删除行,除非它们匹配'test @'。

Tested on the data file:

测试数据文件:

aaaa
bbbtestbbb
ccctest@ccc
test!
dddd

Output:

aaaa
ccctest@ccc
dddd

That seems to meet your requirements.

这似乎符合您的要求。

#2


4  

Use grep:

grep -v 'test[^@]' infile

Usually grep prints matching lines but -v tells it to print non-matching lines.

通常grep打印匹配的行,但-v告诉它打印不匹配的行。

The regular expression matches any occurance of "test" that is followed by anything but a '@'. This is fine if you don't have to expect "test" coming up at the end of a line. If that is the case, use

正则表达式匹配任何“test”的出现,后面除了“@”之外的任何东西。如果您不必期望在一行结束时出现“测试”,那么这很好。如果是这种情况,请使用

grep -E -v 'test([^@]|$)'

I don't think it is worth going into why your solution does not work, because it is broken in so many ways.

我不认为值得讨论为什么你的解决方案不起作用,因为它在很多方面被打破了。

#3


1  

If you flip your question around a bit, it becomes:

如果你翻一下你的问题,它会变成:

How do I filter out all lines from a file that either contains the string 'test@' or does not contain the string 'test'.

如何过滤掉包含字符串'test @'或不包含字符串'test'的文件中的所有行。

This can for example be done in awk like this:

例如,这可以在awk中完成,如下所示:

awk '!/foo/ || /foo@/' testfile

Jonathan's answer also works, I just wanted to give you an alternate version.

Jonathan的回答也有效,我只是想给你一个替代版本。

#4


1  

There is no need for a tmp file if you use ed!

如果使用ed,则不需要tmp文件!

# cf. http://wiki.bash-hackers.org/howto/edit-ed
cat <<-'EOF' | ed -s file
H
,g/test$/d
,g/test[^@]/d
wq
EOF