引用符付きコメントフラグを無視しながら、ファイルからコメントを削除します。

引用符付きコメントフラグを無視しながら、ファイルからコメントを削除します。

で始まるコメントを削除したいと思います#。私は説明したより簡単なアプローチを試しました。ファイルからすべてのコメントを削除する方法は?しかし、いくつかの追加ルールがあります。

  • Aが#引用符付き文字列の一部として表示されると、コメントは開始されません。
  • 文字列は一重引用符または二重引用符で'囲むことができます"
  • 二重引用符で囲まれた文字列には、前にバックスラッシュがある場合は引用符を含めることができ、バックスラッシュ\"はこのように引用されます\\
  • 入力のすべての引用符が一致します。ただし、これは文字列の内容の一部である引用符(つまり"'"有効な"\""文字列)には'"'必要ありません。
  • 引用符付き文字列には改行文字を含めることはできません。
  • #説明には、およびを含む任意の文字を含めることができます'"\
  • すべての#コンテンツはコメントで始まります(例:スティーブン・チャジェラスほとんどのシェルコードはより複雑な規則に従うことを指摘してください。$#コメントで始まらないBashコードを考えてみましょう。

たとえば、次の入力

# comment only
# comments are allowed to contain quotes "' and # number signs
# comments are allowed to contain pairs 'of' "quotes"
some text # with an explanation
some "quoted text # not a comment" # comment
'# not a comment' and '# not a comment either' # comment
"# not a comment containing 'quotes\"" # another comment

次の出力に変換する必要があります。




some text
some "quoted text # not a comment"
'# not a comment' and '# not a comment either'
"# not a comment containing 'quotes\""

私は広く使用されているUnixコマンドラインツール(例えば、、)を使って最新のDebian / Ubuntuシステムでawkこれをやりたいと思います。 POSIX 準拠のソリューションが推奨されますが、POSIX で説明されている機能に厳密に限定されるわけではありません。grepsed

ベストアンサー1

POSIX shスクリプトからコメントを削除することが重要な場合は、次のコードでYESとマークされているコメントのみがコメントであることに注意してください。

echo 1 # YES
echo 2 $# NO foo# NO
echo 3;#YES
# YES
cat << E
# NO
E
echo 4 " # NO \" # NO" \" # YES
echo "5
# NO
$(echo 6 # YES
)
`echo 7 \" # NO \"`
"
eval 'echo 8 # NO, then YES'

(ほとんどの場合、stackexchange構文の強調表示でエラーが発生することがわかります)。

これには数百行awkまたはsedコードが必要です。

csh、、、、などの注釈リーダーで引用符と引用符があるfish他の言語の規則はまったく異なります。perlpythonruby"..."'...'#

もし

  • これはシェル構文とは関係ありません。
  • 引用符がエスケープされていないと仮定できます。
  • 引用符付き文字列には改行文字は含まれていません。
  • すべての引用符が一致します。
  • #スペースやその他の区切り文字が続くだけでなく、引用符以外のすべてがコメントを開始します。
  • 入力は現在のロケールの有効なテキストです。

合格すると基準POSIX 2018以下を意味する場合は、次のことができますsed

sed "s/^\(\(\([^\"'#]\)*\(\"[^\"]*\"\)\{0,1\}\('[^']*'\)\{0,1\}\)*\)#.*/\1/"

POSIX 2018は交互演算子に必要なEREをsedサポートしていませんが、ここでは(EREで)同等の使用を渡します。-E\(a\{0,1\}b\{0,1\}\)*(a?b?)*(a|b)*(a*b*)*ラケシュの答え動作します。

grepgrep標準は完全に一致する行のみを印刷するため、オプションではありません。awkしかし、EREを使用してください。標準awkにはキャプチャグループはありませんが、次のことができるはずです。

awk "match(\$0, /^([^'\"#]|\"[^\"]*\"|'[^']*')*#/) {
       \$0 = substr(\$0, 1, RLENGTH-1)
     }
     {print}"

"(\\.|[^\\"])*"編集者の要件に応じて、またはそれに対応するBREを使用してエスケープ引用符を処理できます。

sed 's/^\(\(\([^"\\'\''#]\)*\(\\.\)\{0,1\}\("\([^"\\]*\(\\.\)\{0,1\}\)*"\)\{0,1\}\('"'[^']*'\)\{0,1\}\)*\)#.*/\1/"

または:

awk 'match($0, /^([^'\''"\\#]|\\.|"(\\.|[^\\"])*"|'\''(\\.|[^\\'\''])*'\'')*#/) {
       $0 = substr($0, 1, RLENGTH-1)
     }
     {print}'

どちらもエスケープ引用符も処理します。外部引用符(例foo\"bar # comment:)。

リテラルを取得するために挿入する必要があるバックスラッシュの数を減らすために、ここでは一重引用符を代わりに使用しますが、\\データのリテラル一重引用符は次のように挿入する必要があります'before'\''after'。つまり、バックスラッシュを使用して引用符付き文字列を閉じる'\''最初の文字です。 /translateリテラル(一重引用符で囲まれた文字列の中に一重引用符を挿入できないため)、次に引用符付き文字列を入力します。''before'\'''after'

おすすめ記事