2011-06-30 12 views
5

"test"という単語を含むファイルのすべての行を削除しますが、その行に "test @"が含まれている場合は削除しません。1つの文字列に一致するが、別の文字列に一致しないファイル内の行を削除する - SED、BASH?

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 != *[email protected]* ]] 
       then 
       sed -e "${line_num}"'d' $filetest >> $filetest_tmp 
     fi 
done < $filetest 
cp $syslog_tmp $filetest 

あなたが言うことができるように、私はこれで初心者くさいよ:(

+3

例で「ルート」を使用する場合は、説明に「テスト」を使用しないでください。あなたの例で "testsh"/"test @"を使用するときは、あなたの記述に "test"/"test @"を使わないでください。質問を書くときにはさらに注意してください。お願いします? – hop

答えて

10
sed -e '/test/{/[email protected]/!d;}' 

最初のパターンは、「テスト」を含む行と一致する;彼らは「テストにマッチしない限り、第2のパターンが行を削除します@ 」データファイルでテスト

:。

aaaa 
bbbtestbbb 
[email protected] 
test! 
dddd 

出力:

aaaa 
[email protected] 
dddd 

あなたの要件を満たしているようです。

4

使用grep

grep -v 'test[^@]' infile 

通常 grepプリント一致した行が、 -vは、それが非マッチした行を印刷するように指示します。

正規表現は、 "test"の後に "@"以外のものが続く場合に一致します。これは、行の最後に "テスト"が来ることを期待する必要がない場合は問題ありません。その場合は、

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

を使用し、私はそれが非常に多くの方法で壊れているので、それは、あなたのソリューションが動作しない理由に行く価値があるとは思いません。

1

あなたは少しの周りにあなたの質問を反転した場合、それは次のようになります。

どのように私は、文字列「テスト@」が含まれているか、文字列「テスト」が含まれていないのいずれかのファイルからすべての行をフィルタリングします。例えば

この缶は、このようなawkで行われる:

awk '!/foo/ || /[email protected]/' testfile 

Jonathan's answerも動作しますが、私はあなたに別のバージョンを与えたかったです。

1

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 
関連する問題