更新スクリプトへの入力のクリーンアップ

更新スクリプトへの入力のクリーンアップ

Gitコミットコメントから入力を受け取り、それ自体を更新するbashスクリプトを確認してください。単純化する:

script:

#!/bin/bash

comment=''

printf '%s\n' "$comment"

upgrade_script() {
        # Download latest:
        curl -o updated_script https://path/to/file

        # Get comment:
        new_comment="$(curl https://path/to/comment)"

        # Update comment='' with new_comment:
        sed -i "3,0 s/comment=''/comment='$new_comment'/" updated_script
}

問題は、コメントに中断sedまたはmanglesクン文字が含まれているかどうかです。たとえば、

# that's all she wrote!  => comment='that's all she wrote!
# use /need/ over /want/ => s/comment=''/'use /need/ over /want'/'

もちろん、悪意のある意図がある可能性もありますが、次のような予期しないこともあるかもしれません。

# Remove tmp files by: ' rm -r *;' => comment='Remove tmp files by: ' rm -r *;''

これで問題を解決するのに十分ですか?

コマンドの前に以下を追加しますsed -i

new_comment=$(
    sed \
    -e "s/'/'\"'\"'/g" \
    -e 's/[&\\/]/\\&/g; s/$/\\/; $s/\\$//'<<< "$new_comment"
)

のためbash

  1. '使用。 。 。交換'"'"'

のためsed

  1. エスケープ文字&\および/行終端。

それとも、どのような失敗が起こるのでしょうか?


理想的には、これは何もしませんが、知りたいのですが。

注:

別のソリューション、ファイルとして保存exitスクリプトにを追加し、その後にテキストを追加してから、などsedを使用して印刷することもできます。しかし、それは私の問題ではありません。

#!/bin/bash

code
code
code

# When in need of the comment:
sed -n '/^exit # EOF Script$/$ {/start_xyz/,/end_xyz/ ...}'
# or what ever. Could even record offset and byte-length safely

code
code

exit # EOF Script

start_xyz
Blah blah blah
blaah
end_xyz

これを念頭に置いて、次のように推測します。

comment=<<<'SOF'
...
SOF

SOF早期終了を防ぐには、どちらかを交換するだけです。私の質問はまだ消毒する以上。ありがとうございます。

答え1

以下を組み合わせる必要があるようです。

だから:

#! /bin/bash -

comment=''

printf '%s\n' "$comment"

upgrade_script() {
  local - new_comment quoted_for_sh quoted_for_sed_and_sh
  set -o pipefail

  # Get comment:
  new_comment="$(curl https://path/to/comment)" || return

  quoted_for_sh=\'${new_comment//\'/\'\\\'\'}\'

  quoted_for_sed_and_sh=$(
    printf '%s\n' "$quoted_for_sh" |
      LC_ALL=C sed 's:[\\/&]:\\&:g;$!s/$/\\/'
  ) || return

  curl https://path/to/file |
  # Update comment='' with new_comment:
    LC_ALL=C sed "3s/comment=''/comment=$quoted_for_sed/" > updated_script
}

zsh + perlはbash + sedよりも良い選択ですが:

#! /bin/zsh -

comment=''

print -r -- $comment

upgrade_script() {
  set -o localoptions -o pipefail
  local new_comment quoted_for_sh

  # Get comment:
  new_comment=$(curl https://path/to/comment) || return

  quoted_for_sh=${(qq)new_comment}

  curl https://path/to/file |
  # Update comment='' with new_comment:
    perl -pse "s/comment=\K''/$repl/ if $. == 3
      ' -- -repl=$quoted_for_sh > updated_script
}

NUL文字を含めることができることに注意してくださいcomment。これはzshとその組み込み機能には適していますが、外部コマンドに引数として渡すことはできません。 NULをbash削除します$(...)

これらのリスクを排除するには、curl出力をパイプしてNULを手動で削除するtr -d '\0'か、

new_comment=${new_comment//$'\0'}

またはそのような役割がある場合は終了します。

[[ $new_comment = *$'\0'* ]] && die 'Something dodgy going on'

関連情報