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"
使用するにはsed
(sed
ここで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 -F
awk
を引き続き使用するには、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 で指定されます.)