두 개의 (파이프라인) 셸 명령을 셸 함수에 대한 인수로 전달합니다.

두 개의 (파이프라인) 셸 명령을 셸 함수에 대한 인수로 전달합니다.

다음 쉘 함수를 정의했습니다.

success() {
  printf "[\033[32mSUCCESS\033[0m]\n"
}

failure() {
  printf "[\033[31mFAILURE\033[0m]\n"
}

try() {
  result=$($* 2>&1)
  if [ $? -ne 0 ]; then
    failure
    echo $result
    exit 1
  fi
  success
}

이를 통해 모든 명령을 자동으로 실행하고, 모든 출력을 캡처하고, 표시 SUCCESS하거나 FAILURE메시지를 표시할 수 있습니다. 명령 출력은 명령이 실패한 경우에만 디버깅 목적으로 표시됩니다.

try rm -r $tmp

그러나 나는 그것이 단일 명령으로 제한되어 있고 다른 명령으로 파이프된 명령에 대해 비참하게 실패한다는 것을 깨달았습니다 |.

try git archive --format=tar HEAD | tar xf - -C $tmp

try명령에 대해서만 실행되므로 의 git출력은 의 출력이 아닌 try으로 파이프 됩니다 .targit

git ... | tar ...두 명령을 단일 인수로 전달할 수 있습니까 ?try, 둘 다의 출력을 캡처하고 둘 다 반환 git되는지 확인하십시오 .tar0

내 목표를 달성하기 위해 다른 고려 사항이 있습니까?

답변1

git … | tar …파이프(두 개의 개별 명령이 아닌 두 개의 하위 명령을 포함하는 단일 명령)를 함수에 직접 인수로 전달 하려면 명령이 포함된 문자열을 만들고 eval함수에 내장된 함수를 사용해야 합니다. 이 문자열을 쉘 명령으로 실행합니다.

올바른 인용에 주의하세요. 인수의 경우 포함 스크립트와 동일한 변수를 사용하여 미니 쉘 스크립트인 문자열을 작성합니다. 특히 변수에 파일 이름이 포함된 경우( tmp여기서와 같이) 변수 값이 아닌 변수 확장을 전달해야 합니다. 파일 이름은 쉘 조각이 아니므로 '…"$tmp"…'대신 확장이 필요하기 때문입니다 "…$tmp…". 평가할 때 eval확장된 문자열이 아닌 정확한 문자열을 전달해야 합니다 . 특히, $*거의 항상 잘못된 내용을 읽습니다.공백이나 기타 특수 문자 때문에 쉘 스크립트가 멈추는 이유는 무엇입니까?

try () {
  result=$(eval "$1" 2>&1)
  if [ $? -ne 0 ]; then
    failure
    echo $result
    exit 1
  fi
  success
}
try 'git archive --format=tar HEAD | tar xf - -C "$tmp"'

또 다른 접근 방식은 복합 명령을 함수에 넣는 것입니다. 다시 한 번 정확하게 인용하십시오. "$@"함수의 매개변수를 간단한 명령(별명, 함수, 매개변수가 있는 내장 또는 외부 명령)으로 평가하는 데 사용됩니다 .

try () {
  result=$(eval "$1" 2>&1)
  if [ $? -ne 0 ]; then
    failure
    echo $result
    exit 1
  fi
  success
}
archive_to_directory () {
  git archive --format=tar HEAD | tar xf - -C "$1"'
}
try archive_to_directory "$tmp"

파이프의 상태는 오른쪽의 상태이며 왼쪽의 상태는 무시됩니다. bash에서는(sh에서는 제외) 다음을 통해 파이프라인의 모든 명령 상태에 액세스할 수 있습니다.PIPESTATUS바꾸다.

try () {
  result=$(eval "$1" 2>&1)
  if [ $? -ne 0 ]; then
    failure
    echo $result
    exit 1
  fi
  success
}
archive_to_directory () {
  git archive --format=tar HEAD | tar xf - -C "$1"'
  [[ -n ${PIPESTATUS[*]//[0 ]/} ]]
}
try archive_to_directory "$tmp"

답변2

명령줄에 따옴표를 추가해야 합니다. 이는 불가피합니다.

try "git archive --format=tar HEAD | tar xf - -C $tmp"

그런 다음 함수에서 셸 메타 문자(예: |)는 변수에 저장될 때 특별하지 않으므로 다음이 필요합니다.eval

try() {
  if result=$(eval "$*" 2>&1); then
    success
  else
    failure
    echo $result
    exit 1
  fi
}

아직은 이 부분이 제대로 이해되지 않았다는 느낌이 듭니다. 누군가가 나를 고칠 수 있기를 바랍니다.

관련 정보