쉘 스크립트에서 명령을 호출하여 대부분의 매개변수를 전달하고 매개변수에 공백을 허용합니다.

쉘 스크립트에서 명령을 호출하여 대부분의 매개변수를 전달하고 매개변수에 공백을 허용합니다.

SAS 코드를 일괄적으로 실행하는 명령 주위에 run_sas.sh래퍼가 있습니다. sas일반적인 통화는 다음과 같습니다.

./run_sas.sh -sysin /my_code/my_program.sas -log /my_log_folder/my_program.log
  • run_sas.sh모든 매개변수를 saswith 에 전달합니다 ./sas $*.
  • sas그런 다음 실행 /my_code/my_program.sas하고 로그를 작성합니다 /my_log_folder/my_program.log.
  • 그런 다음 run_sas.sh호출 매개변수를 분석합니다.
  • 그리고 로그를 다음 위치에 복사하세요./admin/.hidden_log_folder/my_program_<today's date>.log

두 가지 사항을 변경하고 싶습니다.

다중 단어 매개변수 활성화

일부 클라이언트는 폴더 및 파일 이름에 공백을 사용하고 실행하도록 요구하기를 절대적으로 원합니다 /their code/their program.sas.

./run_sas.sh -sysin "/their code/their program.sas" -log "/their log folder"

/their code/their program.sas/their log folder단일 인수가 전달되어야 합니다 .sas

특정 매개변수 제거

./sas_utf8때로는 대신 실행해야 ./sas하고 두 번째 스크립트를 유지하기에는 너무 게으른 편이므로 다음과 같은 추가 매개변수를 허용하고 싶습니다.

./run_sas.sh -sysin /my_code/my_program.sas -log /my_log_folder -encoding utf8

전화통화 가능

./sas_utf8 -sysin /my_code/my_program.sas -log /my_log_folder

바꾸다

./sas -sysin /my_code/my_program.sas -log /my_log_folder

가급적이면 에서 이 작업을 수행하려면 어떻게 해야 합니까 ksh?

답변1

먼저 매개변수를 그대로 유지하려면 "$@"not $*(또는 )을 사용하세요. 를 $@사용하는 것처럼 각 매개변수를 별도의 단어로 확장합니다. "$1" "$2"...를 사용하면 $*glob 문자도 문제가 됩니다.

utf8 옵션을 찾으려면 명령줄 인수를 반복하고 유지하려는 인수를 다른 배열에 복사하고 및 가 -encoding표시되면 플래그를 설정할 수 있습니다 utf8.

그런 다음 플래그 변수를 확인하여 실행할 프로그램을 결정하고 이를 "${sasArgs[@]}"명령에 전달하면 됩니다.

그래서:

executable="./sas" # The default, for latin encoding

# Inspect the arguments,
# Remember where the log is written
# Change the executable if the encoding is specified
# Copy all arguments except the encoding to the 'sasArgs' array
while [[ "$#" -gt 0 ]]; do
    case "$1" in
        -encoding) 
            # change the executable, but do not append to sasArgs
            if [[ "$2" = "utf8" ]]; then
                executable="./sas_u8"               
                shift 2
                continue
            else
                echo "The only alternative encoding already supported is utf8" >&2
                exit 1
            fi
            ;;
        -log) 
            # remember the next argument to copy the log from
            logPath="$2"
            ;;
    esac
    sasArgs+=("$1")
    shift
done

#  To debug: print the args, enclosed in "<>" to discover multi word arguments
printf "Command and args: "
printf "<%s> " "$cmd" "${sasArgs[@]}"
printf "\n"
# exit # when debugging

# Actually run it
"$executable" "${sasArgs[@]}"

# Copy the log using $logPath
# ...

최종 printf호출은 각 인수를 둘러싸서 실행할 인수를 인쇄하므로 <>공백이 있는 인수가 변경되지 않은 상태로 유지되는지 확인할 수 있습니다. (실행할 수는 있지만 두 인수 와 단일 인수를 echo "${sasArgs[@]}"구별하지 않습니다 .)foobarfoo bar


두 매개변수 쌍이 아닌 단일 매개변수를 찾는 경우 첫 번째 부분은 루프를 사용하여 더 간단하게 만들 수 있습니다 for.

for arg in "$@" do
    case "$arg" in
        -encoding-utf8) 
            # change the executable, but do not append to the array
            executable="./sas_u8"               
            continue
            ;;
     esac
     sasArgs+=("$arg")
done

일반 POSIX sh로 변환할 수도 있습니다. 루프 for는 주어진 목록의 복사본을 만들기 때문에 복사된 인수는 set -- "$@" "$arg"배열을 사용하는 대신 위치 인수(추가)로 다시 저장할 수 있습니다.

게다가 처음에 인코딩 매개변수를 알고 있다면 전체 트랜잭션이 훨씬 단순해집니다. 그런 다음 ( 및 )을 확인 하고 를 사용하여 제거하면 $1충분합니다 .$2shift

(저는 Debian에서 Bash와 ksh93 버전 모두를 사용하여 위 스크립트를 테스트했습니다. 저는 ksh에 익숙하지 않아서 뭔가 놓쳤을 수도 있습니다. 하지만 Bash의 배열은 ksh에서 복사되었으므로 똑같이 잘 작동할 것으로 기대합니다. 시간. )

관련 정보