それでしばらく前に見ました。これ2つの「マーカー」の間のテキストを抽出するためのスニペット:
# Usage: extract file "opening marker" "closing marker"
while IFS=$'\n' read -r line; do
[[ "$extract" && "$line" != "$3" ]] &&
printf '%s\n' "$line"
[[ "$line" == "$2" ]] && extract=1
[[ "$line" == "$3" ]] && extract=
done < "$1"
(ここでは関数からランダムに削除し、というファイルに入れました。extract
)これで、「ほとんどの」タグペアで正しく機能します。しかし、私はそれが常に動作しているわけではないことがわかりました。
N個の反復文字を含む元のフラグメントの例に従います(SOのフォーマットエラーのために「`」の代わりに「#」を使用)。
###sh
test
###
これは機能しますextract file '###sh' '###'
が、次のマークアップを使用する場合:
###
test
###
そうしましたが、うまくextract file '###' '###'
いきませんか?
スクリプトの条件が正しく評価されていることがわかりますが、変数は使用されている場合extract
と同じです。1
set -x
どうなりますか?
PS:もちろん、「動作しない」という言葉は、うまくいかないとインスタンスに何も印刷しないという意味です。
上記の2つの出力例してはいけないタグを含める(2つのタグ間で抽出されたテキストのみ)...
可能であれば、bash / shellソリューションをお勧めします。
答え1
[[ "$line" == "$2" ]]
他の人があなたの質問の説明で述べたように、開始条件が満たされるとextract
1に設定されますが、次の行で[[ "$line" == "$3" ]]
終了条件も満たされると、スクリプトはextract
空の文字列にリセットされるため、スクリプトは機能しません。
固定スクリプトは次のとおりです。
# Usage: extract file "opening marker" "closing marker"
while IFS=$'\n' read -r line; do
if [ "$extract" ]; then
if [[ "$line" == "$3" ]]; then
extract=
else
printf '%s\n' "$line"
fi
elif [[ "$line" == "$2" ]]; then
extract=1
fi
done < "$1"
そして、これが必要な場合は、@Freddyが提案したように、印刷されるテキストに閉じるタグが必要なわずかに変更されたバージョンがあります。
# Usage: extract file "opening marker" "closing marker"
while IFS=$'\n' read -r line; do
if [ "$extract" ]; then
if [[ "$line" == "$3" ]]; then
printf '%s\n' "${lines[@]}"
lines=() extract=
else
lines+=( "$line" )
fi
elif [[ "$line" == "$2" ]]; then
extract=1
fi
done < "$1"
(行は配列に蓄積され、lines
終了マークが表示されたときにのみ印刷されます)
答え2
$ 2が表示されるたびに、抽出変数に遷移ロジックを追加します。ご指摘いただいたxhieneに感謝!
[[ $line == $2 ]] && case $extract in '') extract=1;; *) extract=; esac
次に、抽出変数に対する$ 3の依存関係を削除します。
HTH。