実施例1

実施例1

result.txt表示するためのサンプルテキストファイルがあります。

{HEX}.A.Bs
{HEX}.A.Bss
{HEX}.A.Bsss
{HEX}.A.Bssss

ただし、実際のアプリケーションでは、コンテンツにresult.txt次の文字を1行ずつ含めることができます。

/usr/local/abc.txt
/var/tmp/
png
OIPOP()_+(_)&*#)@IOJDNU*@Utest

Bashスクリプトのパラメータを介して1行の文字列を削除したいと思います。したがって、私のbashスクリプトにはtest.sh次のコードがあります。

!/bin/sh
#test.sh
result=result.txt
del="$1"
sed -i "/$del/d" $result
cat result.txt

実施例1

したがって、削除するには、"{HEX}.A.Bs"パラメータを使用して次のスクリプトを実行します。

./test.sh "{HEX}.A.Bs"

"{HEX}.A.Bs"これにより、insideという文字列が削除されます。result.txt しかし、中にあるすべては result.txt 削除されました。予想される出力は次のようになります。

{HEX}.A.Bss
{HEX}.A.Bsss
{HEX}.A.Bssss

実施例2

削除したい場合"{HEX}.A.Bss"

./test.sh "{HEX}.A.Bss"

上記の例文字列を1つだけ残す "{HEX}.A.Bs" ~へ result.txt。文字列のみを削除する必要があります"{HEX}.A.Bss"。したがって、予想される結果は次のとおりです。実施例2次の結果を生成する必要があります。

{HEX}.A.Bs
{HEX}.A.Bsss
{HEX}.A.Bssss

ここでコードにどのような問題があるのか​​わかりますか?

答え1

文字列に一致する行を削除するには、内部編集用のGNU awk(GNU sedと同じ)などのリテラル文字列を理解するツールを使用します。

del="$1" awk -i inplace '($0"") != ENVIRON["del"]' "$result"

答え2

使用perl-i最新の実装でサポートされているいくつかの非標準オプションは、sed実際には以下で借用されていますperl):

LINE_TO_REMOVE='{HEX}.A.Bs' perl -i -nle '
  print if $_ ne $ENV{LINE_TO_REMOVE}' -- "$file"

使用するにはsedsedここでGNUまたは互換性があると仮定)最初に必要です。一致のために、文字列から正規表現演算子をエスケープします。.例で使用されているエスケープされていない文字を含めると、すべての単一文字と一致します)開始と終了に^それぞれ固定します$

string='{HEX}.A.Bs'
regexp='^'$(printf '%s\n' "$string" | sed 's:[][\\/.^$*]:\\&:g')'$'
sed -i -e "/$regexp/d" -- "$file"

(また、$stringファイルに有効なテキストが含まれているとします)。

答え3

コードの問題は、{HEX}.A.Bss部分文字列が正常に一致することです。すべてワイヤー。

文字列に次のものが含まれていないとします。エスケープする必要がある文字、代わりに使用することができます

sed "/^$string\$/d" filename

つまり、線の始めと終わりにパターンを固定します。

パターンができた時からするエスケープする必要がある文字が含まれています(、単一文字と一致)。を使用するか、文字列比較を実行する方が.安全です。grep -Fawk

を引き続き使用するには、sed文字列内のすべての点が点で一致していることを確認し、それ以外は一致しないことを確認してください。

pattern=$( printf '%s\n' "$string" | sed 's/[.]/[.]/g' )
sed "/^$pattern\$/d" filename

文字列に正確に一致する行を削除するには、次のようにします。

grep -v -xF -e "$string" filename >newfile && mv newfile filename

ここで使用されるオプションgrep

  • -v:テストの意味を否定します(例:すべての行)。いいえ一致するパターンが抽出される。
  • -x: 与えられたパターンに従うには、ライン全体が必要です。
  • -F:パターンを正規表現ではなく文字列として扱います。
  • -e:「次のパラメータはモードです。」値が$stringダッシュで始まる場合は必須です。

元のファイルのメタデータ(所有権、権限など)をできるだけ多く保存するには、ファイルをコピーしてコピーにアクションを適用し、grep結果を元のファイルにリダイレクトします。

cp filename filename.tmp &&
grep -v -xF -e "$string" filename.tmp >filename
rm -f filename.tmp

答え4

私は \bこれが単語の境界に関するものだと思い、行に"{HEX}.A.Bs anotherword"orが含まれている場合"{HEX}.A.Bs filename"(つまり、文字列にスペースとファイル名に「filename」が含まれている場合)にも削除されます。

したがって、特定の「{HEX}.AB」のみを削除するには、次のようにすることをお勧めします。

$ sed '|^'"$del"'$|d' $result  

"$del"文字列の間に単一引用符を入れて渡す文字列を含めると、パターンではなくそのまま'正確に一致することを意味します。

真珠:

perl -pe "s|^\Q$del\E$||g;" $result | sed '/^$/d'   

\Q=>パターンメタ文字を引用(無効)します。\E

その場で編集するには(ファイルを直接変更/編集)、以下を使用できます。

$ perl -pe "s|^\Q$del\E$||g;" $result | sed '/^$/d' > tmpfile && mv tmpfile $result  

awkを使用するには:

$ awk -v d=$del  '$0 != d' $result > tmp && mv tmp $result

grepを使用するには:

$grep -vxF "$del" $result > tmp && mv tmp $result

-F、--fixed-strings, --fixed-regexp は、PATTERN を固定文字列リストとして解釈します。
-V、--invert-match 一致しない行を選択するには、一致の意味を反転します。 (-v は POSIX で指定されます.)
-X、--line-regexpは、行全体と正確に一致する一致のみを選択します。 (-x は POSIX で指定されます.)

関連情報