업데이트 스크립트에 대한 입력 정리

업데이트 스크립트에 대한 입력 정리

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'

관련 정보