Bash 명령줄의 읽기, 에코 및 grep 명령 이해

Bash 명령줄의 읽기, 에코 및 grep 명령 이해

이 bash 라인에서 어떤 일이 일어나는지 단계별로 설명할 수 있는 사람이 있나요? 저는 여기에 처음 왔으며 특히 다음에서 이 코드가 어떻게 작동하는지 이해하려고 노력하고 있습니다 echo.

read char; echo -e "YES\nNO\n" | grep -i $char

답변1

char해당 행의 명령은 아마도 사용자로부터 대화식으로 문자열을 변수로 읽어옵니다 .

echo+ 파이프라인 은 grep입력된 문자열이 긍정인지 여부를 확인하려고 시도합니다. 대소문자를 구분하지 않고 단어 YESNO입력된 문자열(입력된 문자열을 패턴으로 사용)을 비교하여 이를 수행합니다 . 사용자가 단어에 있는 대문자나 소문자 또는 하위 문자열을 입력하면 YES결과는 다음과 같습니다 YES. 문자열에 있는 대문자나 소문자 또는 하위 문자열을 입력한 경우 NO결과는 입니다 NO. 다음과 같은 것을 입력하면 maybe빈 출력이 발생합니다.

이 접근 방식의 단점은 예를 들어 사용자가 를 입력하면 점을 모든 문자와 일치하는 정규식으로 처리하는 것처럼 및 .둘 다 일치한다는 것입니다. 에 대한 호출에서 가 인용되지 않았 으므로 사용자가 입력과 같은 쉘 글로빙 패턴을 입력하는 경우 시스템에 대한 서비스 거부 공격을 일으킬 가능성도 있습니다 (예:YESNOgrep$chargrep/*/*/*/*/../../../../*/*/*/*bash/POSIX 쉘에서 변수를 인용하는 것을 잊어버린 경우의 보안 영향). 예를 들어 명령을 사용하면 출력이 혼동될 수도 있습니다. -r -o -e . /(모든 비바이너리 파일의 모든 문자가 해당 파일의 일부인 파일 경로 이름이 앞에 오는 한 줄에 출력됩니다.)

당신이 보여주는 코드는 본질적으로 사용자 입력을 사용한다는 점에서 "이상하고 특이합니다".암호즉, 사용자 입력을 다음과 같이 사용합니다.무늬, 정적 테스트데이터이 가변 패턴에 반대합니다. 이는 일반적으로 수행하는 작업, 즉 사용자로부터 입력을 받아 이 변수 ​​데이터를 정적 패턴에 대해 테스트하는 것과 반대입니다.

다음과 유사한 코드를 사용하는 것이 더 일반적입니다.

read -p 'Yes/[N]o: ' yesno
if [[ $yesno == [Yy]* ]]; then
   # code for affirmative
else
   # code for non-affirmative
fi

위의 코드는 사용자로부터 문자열을 읽고 문자열이 문자로 시작하는지 테스트 y합니다 Y. if만약 그렇다면 문의 첫 번째 분기가 선택되지만, else그렇지 않으면 기본적으로 분기가 선택됩니다.

또한 전체 단어에 대해 테스트하거나 대소문자를 구분하지 않는 일치 여부를 테스트하거나 확인을 통해 적절한 입력 루프를 수행할 수도 YES있습니다 [Yy][Ee][Ss].

while true; do
    read -p 'Yes/No: ' yesno

    if [ "$yesno" = Yes ] || [ "$yesno" = No ]; then
        break
    fi

    echo 'Please enter "Yes" or "No"' >&2
done

# $yesno is either Yes or No here

(또는 이와 유사한 것).

위의 두 예제 코드 모두 사용자 입력을 데이터로만 사용하고 패턴으로는 사용하지 않는 방법에 주목하세요.

원래 명령을 약간 관용적인 것으로 최소한으로 다시 작성하면(그러나 기능적으로 다르며 아마도 완벽하지는 않음) 다음과 같이 바뀔 것입니다.

read yesno; printf '%s\n' "${yesno^^}" | grep -i -w -E 'yes|no'

이는 대문자를 반환 YES하거나 NO사용자가 yes또는 를 입력한 경우를 반환합니다 no. 예를 들어 이는 사용자가 e에 대한 것 이상의 내용을 입력해야 하므로 기능적으로 다릅니다 .yes

답변2

이제 각 명령을 차례로 살펴보겠습니다.

read char

이는 표준 입력(일반적으로 키보드이지만 간접 파일이거나 파이프 스트림일 수 있습니다. 아래 참조)에서 읽고 수신된 데이터를 이름이 지정된 변수에 넣습니다 char.

echo -e "YES\nNO\n"

echo제공된 매개변수를 표준 출력(일반적으로 터미널)에 표시합니다. 스위치 -e를 사용하면(항상 그런 것은 아니지만 echo종종 일관된 구현과 관련하여 문제가 있음) e특정 문자를 스케이프하여 기본적인 형식을 지정할 수 있습니다. 이 경우에는 ewline 의 약칭인 \n이스케이프된 을 사용하고 있습니다 .nn

grep -i $char

grep제공된 패턴과 일치하는 항목이 있는지 확인하기 위해 제공된 입력을 검색하는 도구입니다. 스위치 -i는 대소문자를 구분하지 않고 검색하도록 지시합니다 i.

와 명령 사이 |는 "파이프"입니다. 이는 첫 번째 명령의 출력을 두 번째 명령의 입력에 연결합니다. 즉, 이 말뭉치에서 변수의 내용에 반영된 패턴을 검색하게 됩니다 .echogrepgrepchar

YES
NO

이 명령 시퀀스의 실제 결과는 제공된 입력을 보는 것입니다(변수 이름을 기반으로 단일 문자로 가정하지만 확인되지 않음). 이 문자가 Y, E, S, y, e, 또는 인 경우 s출력은 입니다 YES. 이 문자가 N, O, n또는 이면 o출력은 입니다 NO. 그러나 (예를 들어) 입력이 yo또는 ne이면 아무것도 출력되지 않습니다.

앞서 언급한 것처럼 입력이 한 문자라는 가정은 확인되지 않습니다. 이것은 주어진 예제 명령 시퀀스의 유일한 안티패턴이 아닙니다. 예를 들어 변수는 인용되지 않습니다. grep정규식 와일드카드에 대해 입력을 검사하지 않고 정규식 도구( )를 사용하고 있습니다.

답변3

에서 "문자"(문자열이 아님)를 읽습니다 /dev/stdin. 의미: 직접 입력하세요.

그러면 두 줄이 출력됩니다 /dev/stdout. 콘솔을 의미합니다.

그리고 파이프("|")를 통해 대소문자를 구분하지 않는 입력 버전에 대해 grep됩니다.

즉, "bar"를 입력하면 뚜렷한 출력 없이 간단히 종료되지만 "y"를 입력하면 "Y"를 강조 표시할 가능성이 가장 높은 "YES" 줄이 출력됩니다.

관련 정보