私の変数には複数行の文字列があります$PAT
。$PAT
ファイル内で検索する必要があります$FILE
。その場合は、削除されたファイル$PAT
を$FILE
印刷する必要があります$PAT
。見つからないと$PAT
何も印刷されません。$PAT
特殊文字が含まれており、文字通り一致する必要があるかどうかはわかりません。たとえば、$PAT
裏側//\/\\|*
で正確に同じ8文字の文字列を検索する必要があります$FILE
。
実際の使用は、既存のファイル/スクリプトにテキストをインストールして削除することです。$PAT
に追加するには、以前に追加された$FILE
かどうかを知りたいです。$PAT
既にある場合$FILE
、なしで出力すると$PAT
簡単に除去できます。
(Androidデバイス)にこれらのスクリプトが必要な唯一のシステムはBusyBoxです。 Perlや他のスクリプト言語はありません。
答え1
完全な行を一致させたい場合は、$PAT
解決策があります。完全な行とは、一致する場合は$FILE
3つのサブファイル(f1、f2、およびf3)に分割できることを意味します。
cat f1 f2 f3
はい$FILE
、- f2は
$PAT
。
f1 および/または f3 は空にすることができます。
まず、f2ファイルを作成します。
cat << EOF > f2
$PAT
EOF
次に、$ FILEとf2を比較し、結果を保存します。
diff $FILE f2 > diff_res
res=$?
0の場合、$res
f1とf3は空で、$ FILEは$ PATと同じです。この場合、空のファイルが欲しいとします。
diff_res
""で始まる行が含まれている場合、>
f2には少なくとも$ FILEにない行が含まれます。テストを受けてください:
grep -q '^> ' diff_res
test $? -eq 0 && echo "PAT not found"
diff_res
" "で始まる行が含まれていない場合、f2>
のすべての行は$ FILEにありますが、連続していない可能性があります。連続型の場合、diff_res
以下が含まれます。
- ""で始まらない限り、行
<
(f1またはf3が空の場合) - 2行は ""で始まらず、
<
最初の行は常に1d
""または"1、"で始まります。
これをテストするには、次のものがあります。
nb=$(grep -v "^< " diff_res | wc -l)
if test $nb -gt 2; then
pat_found=0
elif test $nb -eq 1; then
pat_found=1
else
pat_found=$(sed -n -e '1{/^1d/p;/^1,/p}' diff_res | wc -l)
fi
その後、pat_foundが1の場合、$ PATを持たないファイルはdiffの結果になります。これには<
" "で始まり、次の2文字のない行のみが含まれます。
grep '^< ' diff_res | cut -c 3-
完全で再構成されたスクリプトは次のとおりです。
# Output the desired result on stdin.
f2=/tmp/f2 # Use of PID or mktmp would be better'
diff_res=/tmp/diff_res # Use of PID or mktmp would be better'
cat << EOF > $f2
$PAT
EOF
diff $FILE $f2 > $diff_res
if test $? -ne 0; then
grep -q '^> ' $diff_res
if test $? -ne 0; then
nb=$(grep -v "^< " $diff_res | wc -l)
if test $nb -eq 1; then
grep '^< ' $diff_res | cut -c 3-
elif test $nb -eq 2; then
pat_found=$(sed -n -e '1{/^1d/p;/^1,/p}' $diff_res | wc -l)
test $pat_found -eq 1 && grep '^< ' $diff_res | cut -c 3-
fi
fi
fi
rm -f $f2 $diff_res
答え2
私はあなたがメモリに合ったテキストファイルを書き換えると仮定します(設定ファイルを書き換えるようです)。
次のスクリプトは、シェル組み込みとcat
。ファイルの内容から最初の出現を引いた内容を印刷します$PAT
。$PAT
それ以外の場合は何も印刷されません。
contents=$(cat "$FILE")
case $contents in
*"$PAT"*)
echo "${contents%%$PAT*}${contents#*$PAT}";;
esac
このコードスニペットは、ファイルにヌルバイトが含まれておらず、単一の改行文字で終わり、ダッシュで始まらないと仮定します。また、パターンが改行文字で終わると、ファイルの末尾にパターンが見つかりません。次のより複雑なコードスニペットは、任意のテキストファイルを処理します。
contents=$(cat "$FILE"; echo a)
contents=${contents%a}
case $contents in
*"$PAT"*)
contents="${contents%%$PAT*}${contents#*$PAT}"
dashes=${contents%%[!-]*}
echo -n "$dashes"
echo -n "${contents#$dashes}";;
esac
(あなたが提案した動作は、パターン全体を含むファイルと空のファイルを区別することを不可能にします。)
実際に提案された中間機能を使用するよりも、追加/削除スクリプトを直接実装する方が簡単です。
contents=$(cat "$FILE"; echo a)
contents=${contents%a}
append=
case $contents in
*"$PAT"*) contents="${contents%%$PAT*}${contents#*$PAT}";;
*) contents="$contents$PAT"
esac
dashes=${contents%%[!-]*}
{ echo -n "$dashes"; echo -n "${contents#$dashes}"; } >"$FILE.new"
mv -- "$FILE.new" "$FILE"
答え3
ファイルを文字ごとに読み込みます。その文字が変数の最初の文字と一致すると、次の文字が比較されます。変数全体が一致しない場合に返されます。実装することもできますさらに進化したアルゴリズムより速く実行するには、言語がシェルなので、とにかく非常に遅くなります。