sourcetip

Bash 스크립트에서 인수를 반복하는 방법

fileupload 2023. 4. 18. 23:15
반응형

Bash 스크립트에서 인수를 반복하는 방법

셸/배시 스크립트를 만들고 싶은 복잡한 명령어가 있습니다.을 그 ... ... 쓸 수 .의 관점에서 쓸 수 있다.$1★★★★★★★★★★★★★★★★★★:

foo $1 args -o $1.ext

스크립트에 여러 개의 입력 이름을 전달할 수 있기를 원합니다.어떻게 하면 좋을까요?

그리고 물론 파일명에 공백이 있는 파일명은 취급하고 싶습니다.

"$@"모든 인수를 나타냅니다.

for var in "$@"
do
    echo "$var"
done

이것은 각 인수에 대해 반복되며 다른 행으로 출력됩니다.$@는 $*와 같이 동작합니다.단, 따옴표로 둘러싸인 인수는 공백이 있는 경우 올바르게 분할됩니다.

sh test.sh 1 2 '3 4'
1
2
3 4

VonC에 의해 삭제된 답변을 다시 씁니다.

로버트 갬블의 간결한 대답은 그 질문을 직접적으로 다룬다.이것은 공백이 포함된 파일 이름에 대한 몇 가지 문제를 증폭시킵니다.

참고 항목: /bin/sh의 ${1:+"$@"}

본본: : "$@"$*을 사용하다그 이유는"$@"는 인수에 되어 있는 하며, 「스페이스」와 같이 합니다.$* 「」가 되는 경우도 있습니다."$*" ★★★★★★★★★★★★★★★★★★★」"$@"(항상 그렇지는 않지만) 같은 장소에서 동작합니다. 없음, 옴옴 、$@ ★★★★★★★★★★★★★★★★★」$*는 동등합니다(그리고 거의 항상 틀립니다).

그럼, 다른 점은 무엇일까요?$*,$@,"$*" , , , , 입니다."$@"모두 '쉘에 대한 모든 인수'와 관련이 있지만 다른 작업을 수행합니다.둘러싸지 않은 경우, 「」$* ★★★★★★★★★★★★★★★★★」$@ '이들은 각 '단어'(비 공백의 시퀀스)를 별도의 인수로 취급한다. 인용된 는 상당히 인용된 형식은 다르다."$*"된 단일단, "는 공백으로 구분된 문자열로 취급합니다."$@"는 명령줄에서 지정된 인수와 거의 동일하게 처리합니다. "$@"인수가 에는 전혀 되지 않습니다."$*"을 사용하다그렇습니다만, 인식하기 어려울 수도 있습니다만, 차이가 있습니다. 명령어(「」)의 .al.

번째 논제: 공백으로 인수를 처리한 후 다른 명령어로 전달해야 하는 경우 보조할 비표준 툴이 필요할 수 있습니다(또는 어레이를 신중하게 사용해야 합니다)."${array[@]}" "$@"

예:

    $ mkdir "my dir" anotherdir
    $ ls
    anotherdir      my dir
    $ cp /dev/null "my dir/my file"
    $ cp /dev/null "anotherdir/myfile"
    $ ls -Fltr
    total 0
    drwxr-xr-x   3 jleffler  staff  102 Nov  1 14:55 my dir/
    drwxr-xr-x   3 jleffler  staff  102 Nov  1 14:55 anotherdir/
    $ ls -Fltr *
    my dir:
    total 0
    -rw-r--r--   1 jleffler  staff  0 Nov  1 14:55 my file

    anotherdir:
    total 0
    -rw-r--r--   1 jleffler  staff  0 Nov  1 14:55 myfile
    $ ls -Fltr "./my dir" "./anotherdir"
    ./my dir:
    total 0
    -rw-r--r--   1 jleffler  staff  0 Nov  1 14:55 my file

    ./anotherdir:
    total 0
    -rw-r--r--   1 jleffler  staff  0 Nov  1 14:55 myfile
    $ var='"./my dir" "./anotherdir"' && echo $var
    "./my dir" "./anotherdir"
    $ ls -Fltr $var
    ls: "./anotherdir": No such file or directory
    ls: "./my: No such file or directory
    ls: dir": No such file or directory
    $

? 、 이 변수를하지 않습니다셸이 변수를 확장하기 전에 따옴표를 처리하기 때문에 작동하지 않습니다.이 '따옴표'에 $var , 을.eval:

    $ eval ls -Fltr $var
    ./my dir:
    total 0
    -rw-r--r--   1 jleffler  staff  0 Nov  1 14:55 my file

    ./anotherdir:
    total 0
    -rw-r--r--   1 jleffler  staff  0 Nov  1 14:55 myfile
    $ 

있다'고요.He said, "Don't do this!"( 「 」 、 「 」 、 「 」

    $ cp /dev/null "He said, \"Don't do this!\""
    $ ls
    He said, "Don't do this!"       anotherdir                      my dir
    $ ls -l
    total 0
    -rw-r--r--   1 jleffler  staff    0 Nov  1 15:54 He said, "Don't do this!"
    drwxr-xr-x   3 jleffler  staff  102 Nov  1 14:55 anotherdir
    drwxr-xr-x   3 jleffler  staff  102 Nov  1 14:55 my dir
    $ 

셸(모두)은 이러한 작업을 처리하는 것을 특별히 쉽게 하지 않기 때문에 (재밌게도) 많은 Unix 프로그램이 이러한 작업을 잘 처리하지 못합니다.UNIX에서는, 컴포넌트)에는, 및 NUL UNIX 「」, 「」( 「」)를 의 문자를 할 수 .'\0'그러나 셸은 경로 이름 어디에도 공백, 줄 바꿈 또는 탭을 사용하지 않도록 강력히 권장하고 있습니다.또한 표준 Unix 파일 이름에 공백 등이 포함되지 않는 것도 이 때문입니다.

공백이나 귀찮은 문자를 포함한 파일명을 취급할 때는 매우 주의가 필요합니다만, UNIX에 표준이 아닌 프로그램이 필요하다는 것을 오래전에 알았습니다.는 그것을 나는그 it it라고 부른다.escape1.(버전 1.1 1989-08-23)의 )T16:01:45Z).

를 들면, 이런 입니다.escapeSCCS - SCCS - SCCS - SCCS - SCCS 。 일을 에 하는 입니다.delta(체크인을 생각할 것) 및get(체크 아웃을 생각해 주세요).다양한 주장, 특히-y(변경한 이유)에는 공백과 줄바꿈이 포함됩니다. 이후부터는 합니다.$(cmd ...) 및 ""는 .#!/bin/sh맨 앞줄에

:   "@(#)$Id: delget.sh,v 1.8 1992/12/29 10:46:21 jl Exp $"
#
#   Delta and get files
#   Uses escape to allow for all weird combinations of quotes in arguments

case `basename $0 .sh` in
deledit)    eflag="-e";;
esac

sflag="-s"
for arg in "$@"
do
    case "$arg" in
    -r*)    gargs="$gargs `escape \"$arg\"`"
            dargs="$dargs `escape \"$arg\"`"
            ;;
    -e)     gargs="$gargs `escape \"$arg\"`"
            sflag=""
            eflag=""
            ;;
    -*)     dargs="$dargs `escape \"$arg\"`"
            ;;
    *)      gargs="$gargs `escape \"$arg\"`"
            dargs="$dargs `escape \"$arg\"`"
            ;;
    esac
done

eval delta "$dargs" && eval get $eflag $sflag "$gargs"

을 잘 것 은 (탈옥은) . - 탈옥은 필요 없습니다.-e들어 중 입니다.escape

escape은 단순히 할 뿐이며, 를 들어 '인수'나 '인수'와 같이 출력합니다.echo됩니다.eval의 입니다.eval 셸 , 이은 모모 execution execution execution of of of of of of of of of of of의 가 있었습니다.또한 이 프로그램의 출력을 회피할 필요가 있습니다.escape를 참조해 주세요.

    $ escape $var
    '"./my' 'dir"' '"./anotherdir"'
    $ escape "$var"
    '"./my dir" "./anotherdir"'
    $ escape x y z
    x y z
    $ 

다른 프로그램이 있는데al는 인수를 한 줄에1개씩 나열하고 있습니다(더 오래된 버전 1.1 1987-01-27T14:35:49).스크립트를 디버깅할 때 가장 유용합니다.이 스크립트는 명령줄에 삽입하여 실제로 어떤 인수가 명령어에 전달되는지 확인할 수 있습니다.

    $ echo "$var"
    "./my dir" "./anotherdir"
    $ al $var
    "./my
    dir"
    "./anotherdir"
    $ al "$var"
    "./my dir" "./anotherdir"
    $

[추가사항: 이제 다양한 차이점을 보여 줍니다."$@"표기의 예를 다음에 나타냅니다.

$ cat xx.sh
set -x
al $@
al $*
al "$*"
al "$@"
$ sh xx.sh     *      */*
+ al He said, '"Don'\''t' do 'this!"' anotherdir my dir xx.sh anotherdir/myfile my dir/my file
He
said,
"Don't
do
this!"
anotherdir
my
dir
xx.sh
anotherdir/myfile
my
dir/my
file
+ al He said, '"Don'\''t' do 'this!"' anotherdir my dir xx.sh anotherdir/myfile my dir/my file
He
said,
"Don't
do
this!"
anotherdir
my
dir
xx.sh
anotherdir/myfile
my
dir/my
file
+ al 'He said, "Don'\''t do this!" anotherdir my dir xx.sh anotherdir/myfile my dir/my file'
He said, "Don't do this!" anotherdir my dir xx.sh anotherdir/myfile my dir/my file
+ al 'He said, "Don'\''t do this!"' anotherdir 'my dir' xx.sh anotherdir/myfile 'my dir/my file'
He said, "Don't do this!"
anotherdir
my dir
xx.sh
anotherdir/myfile
my dir/my file
$

을 유지하는 것은 .* ★★★★★★★★★★★★★★★★★」*/*커맨드 라인에 표시됩니다.또한 다음 명령을 사용하여 셸의 '명령줄 인수'를 변경할 수 있습니다.

set -- -new -opt and "arg with space"

4가지 선택지 '4가지 를 할 수 있습니다-new , ' , '-opt , ' , 'and, , , ' "arg with space '

음, 꽤 답변이네요 - 아마도 대리인이 더 나은 용어일 겁니다.소스 코드escape도트 성「 」의 .al매우 간단합니다.

#include <stdio.h>
int main(int argc, char **argv)
{
    while (*++argv != 0)
        puts(*argv);
    return(0);
}

그게 다예요.이것은 에 상당합니다.test.sh로 셸로 쓸 수 단, Robert Gamble을 썼을 는 셸 버전에는 al를 참조해 주세요.

, 「 」, 「 」, 「 」라고 쓸 수도 .al단순한 셸 스크립트로 사용합니다.

[ $# != 0 ] && printf "%s\n" "$@"

인수 없이 전달해도 출력이 생성되지 않도록 조건이 필요합니다.printf명령어는 format string 인수만 사용하여 공백 행을 생성하지만 C 프로그램은 아무것도 생성하지 않습니다.

Robert에서 합니다.sh만만 you .한층 더 심플하게(휴대용으로) 할 수 있습니다.

for i in "$@"

는 다음과 같습니다.

for i

즉, 당신은 아무것도 필요 없어요!

$ : is "sis "command prompt") :

$ set a b "spaces here" d
$ for i; do echo "$i"; done
a
b
spaces here
d
$ for i in "$@"; do echo "$i"; done
a
b
spaces here
d

저는 이것에 대해 Kernighan과 Pike의 Unix Programming Environment에서 처음 읽었습니다.

»bash,help for음음 츠키

for NAME [in WORDS ... ;] do COMMANDS; done

if'in WORDS ...;', 없다.'in "$@"'상정하고 있습니다.

라면 '어디로 하다'를 .shift 인수 목록을 큐처럼 처리합니다. ★★shift첫 번째 인수가 삭제되고 나머지 각 인수의 인덱스가 감소합니다.

#this prints all arguments
while test $# -gt 0
do
    echo "$1"
    shift
done

예를 들어 모든 요소를 반복하지 않는 경우 어레이 요소로 액세스할 수도 있습니다.

argc=$#
argv=("$@")

for (( j=0; j<argc; j++ )); do
    echo "${argv[j]}"
done

인수 변수 수인 $#에 대한 루프도 작동합니다.

#! /bin/bash

for ((i=1; i<=$#; i++))
do
  printf "${!i}\n"
done
./test.sh 1 2 '3 4'

출력:

1
2
3 4

baz의 답변을 증폭하면 특정 단어 검색과 같은 인덱스로 인수 목록을 열거해야 할 경우 목록을 복사하거나 변환하지 않고 이를 수행할 수 있습니다.

인수 목록을 이중 대시("--")로 분할하여 하나의 명령어로 대시 앞의 인수를 전달하고 대시 뒤의 인수를 다른 명령어로 전달합니다.

 toolwrapper() {
   for i in $(seq 1 $#); do
     [[ "${!i}" == "--" ]] && break
   done || return $? # returns error status if we don't "break"

   echo "dashes at $i"
   echo "Before dashes: ${@:1:i-1}"
   echo "After dashes: ${@:i+1:$#}"
 }

결과는 다음과 같습니다.

 $ toolwrapper args for first tool -- and these are for the second
 dashes at 5
 Before dashes: args for first tool
 After dashes: and these are for the second
aparse() {
while [[ $# > 0 ]] ; do
  case "$1" in
    --arg1)
      varg1=${2}
      shift
      ;;
    --arg2)
      varg2=true
      ;;
  esac
  shift
done
}

aparse "$@"

getopt 스크립트에서 명령어를 사용하여 명령줄 옵션 또는 파라미터의 형식을 지정합니다.

#!/bin/bash
# Extract command line options & values with getopt
#
set -- $(getopt -q ab:cd "$@")
#
echo
while [ -n "$1" ]
do
case "$1" in
-a) echo "Found the -a option" ;;
-b) param="$2"
echo "Found the -b option, with parameter value $param"
shift ;;
-c) echo "Found the -c option" ;;
--) shift
break ;;
*) echo "$1 is not an option";;
esac
shift

언급URL : https://stackoverflow.com/questions/255898/how-to-iterate-over-arguments-in-a-bash-script

반응형