$@ 변수가 있습니다.

$@ 변수가 있습니다.

다음 스크립트를 사용하면 사용자가 --header를 선택한 다음 file*을 파일 이름으로 삽입하여 모든 유효한 파일에 헤더를 추가할 수 있기를 원합니다.

#!/bin/bash
case "$1" in
--header )
  for filename in "$@"
  do 
  sed -i -e '1 e cat header' "$filename"
  done
  ;;
--footer )
  footer=~/dev/sed/footer
  for filename in "$@"
  do
  cat "$footer" >> "$filename"
  done
  ;;
esac

./tool ​​​​--header file*을 실행하기 위해 도구를 실행하면 다음 오류가 발생합니다: sed: 인식할 수 없는 옵션 '--header'

$@ 변수가 첫 번째 변수 입력(--header)과 일치하려고 하기 때문에 이것이 발생한다는 것을 알고 있지만 이를 중지하는 방법을 모르겠습니다.

답변1

$@에서 첫 번째 요소를 제거하려면 를 사용합니다 shift.

#!/bin/bash
opt=$1
shift
case "$opt" in
    --header )
        for filename in "$@" ; do 
            sed -i -e '1 e cat header' "$filename"
        done
    ;;
    --footer )
        footer=~/dev/sed/footer
        for filename in "$@" ; do
            cat "$footer" >> "$filename"
        done
    ;;
esac

답변2

문제는 루프(over)를 실행할 때 "$@"옵션이 여전히 루프 중인 목록의 첫 번째 요소라는 것입니다. 반복하기 전에 $@with 의 첫 번째 요소를 제거할 수 있습니다.shift


나는 명령줄 구문 분석과 조작을 분리하는 것을 선호합니다.

#!/bin/sh

unset do_header
unset do_footer

# loop until end of valid options...
while true; do
    case $1 in
        --header)   do_header=1 ;;
        --footer)   do_footer=1 ;;
        *)  # assume end of options
            break
    esac
    shift  # we have processed a valid option, shift it off the list
done

# create a temporary file that we will use multiple times
tmpfile=$(mktemp)

# remove temporary file on normal exit (in bash, also on TERM/INT)
trap 'rm -f "$tmpfile"' EXIT

# For each file, copy it to the temporary file,
# then add header and footer as requested.
# Since we clobber the original file with the redirection, 
# we won't be modifying permissions on the file.

# At this point, the valid options (any number of
# --header and --footer options) have been shifted off
# the list of arguments, so the $@ array now presumably only
# contains pathnames of files that are to be modified.

for pathname do
    cp -- "$pathname" "$tmpfile"
    cat ${do_header:+"header"} "$tmpfile" ${do_footer:+"footer"} >$pathname
done

또한 이를 통해 단일 호출로 머리글과 바닥글을 파일 세트에 추가할 수 있습니다.

변수가 설정되고 비어 있지 않은 경우 매개변수 대체가 ${var:+word}확장됩니다.wordvar

답변3

bash를 사용하는 경우 다른 옵션은 다음과 같습니다.

for filename in "${@:2}"

그러면 두 번째 인수부터 시작하여 인수가 제공됩니다. POSIX에서는 이를 지정하지 않으므로 일부 시스템에서는 이를 지원하지 않을 수 있습니다. 일부 쉘은 동일한 기능을 가지고 있지만 다른 구문을 사용할 수 있습니다.

관련 정보