grep 및 명령줄 인수 사용

grep 및 명령줄 인수 사용

내용이 포함된 파일이 있습니다 f1.

james john joe  
marie james  
joe   
don marie

grep쉘 스크립트에서 다음을 사용하여 s1.sh각 줄의 명령줄 매개변수 발생을 출력 하고 싶습니다 .

#!/bin/bash   
for ((i = $# ; i > 0 ; i-- ))  
    do  
        grep -c $i f1  
    done

다음과 같이 실행한다고 가정해 보겠습니다.

s1.sh james joe

스크립트가 변수를 i위치 매개변수로 해석하도록 하려면 어떻게 해야 합니까?

답변1

스크립트의 인수를 한 번에 하나씩 사용하려는 경우 grep산술 루프를 수행할 필요가 없습니다 for.

#!/bin/sh

for pattern do
    grep -c -e "$pattern" f1
done

for루프는 스크립트의 매개변수인 위치 매개변수를 반복합니다. 각 반복에서 이 값은 $pattern다음 명령줄 인수가 됩니다.

또한 대시로 시작하는 패턴이 options 로 잘못 해석되지 않도록 하기 위해 -e위의 방법을 사용합니다 . 또한 단어 분리 및 파일 이름 글로빙을 방지하기 위해 패턴을 참조했습니다.grepgrep

패턴이 실제로 정규 표현식이 아닌 문자열인 경우 grepwith 사용을 고려하세요 -F.

위치 인수 목록을 사용할 수 "$@"있으며 위의 루프는 이를 암시적으로 사용합니다. 반복하려면 "$@"다음을 사용하십시오.

for pattern in "$@"; do
   ...
done

인용은 필수적입니다. 그렇지 않으면 스크립트 인수에 대해 토큰화 및 파일 이름 일치를 수행하게 됩니다.

이 답변에는 쉘 코드가 필요하지 않으므로 -line을 사용하고 bash있습니다 ./bin/sh#!

답변2

스크립트가 변수를 i위치 매개변수로 해석하도록 하려면 어떻게 해야 합니까?

아마도 Bash에서 변수로 인덱스된 위치 인수를 얻는 가장 간단한 방법은 배열 슬라이스 표기법을 위치 인수에 $@.extended 에 적용하는 것입니다."${@:n:k}"N도착하다n+k-1에서 까지 "${array[@]:n:k}"배열 요소 로 확장하는 것과 같습니다."${array[n]}""${array[n+k-1]}"N그리고케이평가를 위해 쉘 산술을 사용하므로 예를 들어 position 에 인수가 하나만 "${@:a+b-1:1}"주어 지면 이를 수행할 수 있습니다 ."${@:i:1}"i

또는 간접 확장 ${!var}도 위치 인수를 처리하므로 예를 들어 with 가 i=2제공 "${!i}"됩니다 "$2". 음, 이것도 위의 것보다 짧습니다. 반면에 namerefs는아니요위치 매개변수를 사용하면 declare -n ref=2오류가 발생합니다...

예를 들어 참조하십시오.Bash는 포인터 사용을 지원합니까?

또 다른 접근 방식은 위치 인수 목록을 명명된 배열에 복사한 다음 일반적인 방법으로 색인을 생성하는 것입니다. args=("$@")복사해서 사용하세요 "${args[i]}". 여기서도 인덱스는 산술 확장입니다.


물론, 위치 매개변수에 액세스하려는 경우증가평소와 같이 순서에는 실제로 표시된 역순이 필요하지 않으며 Kusalanda의 답변에 표시된 것처럼 for x in "$@"; do ...or 을 사용하면 됩니다.for x do ...

그러나 동일한 루프 구성을 사용하여 위치 인수 목록을 먼저 뒤집을 수도 있습니다. 예를 들어 dd cc bb aa, 이름 지정자, 역참조 또는 배열이 없는 일반 sh에서도 다음과 같이 인쇄됩니다.

set -- aa bb cc dd 
first=1
for x in "$@"; do
    # on first iteration, clear the list
    [ "$first" = 1 ] && set --  
    first=
    set -- "$x" "$@" 
done
echo "$@"

관련 정보