kill
유틸리티가 공백 문자와 개행 문자로 구분된 인수를 허용할 수 있다는 것을 확인했습니다 .
$ sleep 120 & sleep 240 &
[1] 75341
[2] 75342
$ /bin/kill $(echo "75341 75342")
[1]- Terminated: 15 sleep 120
[2]+ Terminated: 15 sleep 240
$ sleep 120 & sleep 240 &
[1] 75577
[2] 75578
$ /bin/kill $(echo -e "75577\n75578")
[1]- Terminated: 15 sleep 120
[2]+ Terminated: 15 sleep 240
$
예를 들어 줄바꿈으로 구분된 매개변수를 허용하는 경우 유틸리티 자체에 따라 달라지는 것이 맞나요?
답변1
인용하지 않았으므로 $(echo -e "75577\n75578")
이를 처리하는 것은 쉘에 달려 있습니다.
쉘이 얻은 내용을 구문 분석하는 방법은 IFS(내부 필드 구분 기호)라는 변수에 따라 다릅니다. 기본적으로 공백, 탭 및 개행 문자가 포함되어 있습니다. 즉, 이 세 문자의 조합은 인수 사이의 유효한 구분 기호로 간주됩니다.
줄 바꿈을 포함하지 않는 문자열로 설정하면 명령이 \n
포함된 매개변수를 수신하고 실패합니다.
$ touch a b
$ echo "$IFS" | od -c
0000000 \t \n \n
0000004$
$ ls -l a b
-rw-r--r-- 1 jlliagre jlliagre 0 Nov 12 15:04 a
-rw-r--r-- 1 jlliagre jlliagre 0 Nov 12 15:04 b
$ ls -l $(printf "a\nb")
-rw-r--r-- 1 jlliagre jlliagre 0 Nov 12 15:05 a
-rw-r--r-- 1 jlliagre jlliagre 0 Nov 12 15:05 b
$ IFS=" "
$ ls -l $(printf "a\nb")
ls: cannot access a
b: No such file or directory
$
답변2
유틸리티의 매개변수는 다음과 같습니다.문자열 목록, 단일 문자열이 아닌. 따라서 유틸리티에는 인수 사이에 구분 기호 개념이 없습니다. 매개변수는 목록의 개별 요소일 뿐이며 사이에는 아무 것도 없습니다.
문자열을 매개변수 목록으로 분할하는 엔터티는 셸입니다. 쉘은 /bin/kill $(echo "75341 75342")
실행 과 마찬가지로 명령줄을 실행합니다.시리즈 확장. 구체적으로:
- 명령은 토큰으로 구분됩니다. 이 규칙에 대해 자세히 설명하지는 않겠습니다. 토큰은 기본적으로 최상위 공백을 포함하지 않는 구두점 또는 문자 시퀀스입니다. 여기서 토큰은 문자열
/bin/kill
과 명령 대체이며$(echo "75341 75342")
, 그 자체는$(…)
연산자와 토큰 으로echo
구성 됩니다75341 75342
. - 명령 대체 연산자에서 명령을 실행합니다. 이는 명령 이름
echo
과 단일 매개변수를 사용하는 간단한 명령입니다75341 75342
. (따옴표는 쉘 구문의 일부이며 명령에 대한 인수가 되는 문자열을 구분합니다.) - 이 명령의 출력은
75341 75342
newline 입니다
. 쉘은 이 출력을 취하고 최종 개행 문자를 제거하여 string 을 생성합니다75341 75342
. - 명령 대체 연산자는 목록 컨텍스트(큰따옴표 제외)에서 사용되기 때문에분사그리고파일 이름 확장자. 단어 분할에는 문자열을 가져와 변수 값에 따라 문자열 목록으로 분할하는 작업이 포함됩니다
IFS
. 기본적으로IFS
공백, 탭 및 줄 바꿈이 포함되므로 문자열은 이러한 문자의 순서에 관계없이 분할됩니다. 두 문자열75341
의 합계 목록이 됩니다75342
. 파일 이름 확장은 여기서 아무것도 변경하지 않습니다. /bin/kill
이제 ,75341
및 3개의 문자열을 포함하는 목록이 있습니다75342
. 이는/bin/kill
두 개의 인수와 를 사용하여75341
명령으로 실행 됩니다75342
.
명령을 사용하면 /bin/kill $(echo -e "75577\n75578")
확장자가 거의 동일합니다. 3단계에서는 출력이 생성됩니다 7534175342
. 4단계에서 줄바꿈과 공백은 동일하게 유효한 단어 구분 기호이므로 75341
단어 분할로 인해 이전과 동일한 목록이 생성됩니다 . 75342
따라서 5단계에서는 정확히 동일한 명령을 실행합니다.
보시다시피 인수 분리를 결정하는 단계는 셸에서 수행되는 토큰화 단계입니다. 값을 변경하여 이 단계를 시도해 볼 수 있습니다 IFS
. 예를 들어, 다음은 동일한 명령을 다시 생성합니다.
IFS=+
/bin/kill $(echo "75341+75342")
답변3
$( )
줄을 공백으로 바꾸는 구조 인 것 같아요 . 그냥 사용하세요 echo $(echo -e "75577\n75578")
.
지금 시도해 보세요
cat <<EOF | kill
1234
5678
EOF
(적절한 값으로).
답변4
이것은 전적으로 에 관한 것이 아닙니다 kill
. (즉)을 사용하더라도 ls
다음과 같은 동작이 발생합니다.
> touch file1 file2
> ls $(echo -e "file1 file2")
file1 file2
> ls $(echo -e "file1\nfile2")
file1 file2
이는 명령 자체와 관련이 없고 bash가 스크립트를 처리하는 방법과 관련이 있기 때문입니다. "스크립트" 측면에서 보면 내 말은 더 명확해집니다. 명령을 파일로 리디렉션하고 chmod를 777로 실행한 후 다음을 실행해 보십시오.
> touch file1 file2
> ls $(echo -e "file1\nfile2")
file1 file2
> echo -e 'ls $(echo -e "file1\nfile2")' > tryme.sh
> cat tryme.sh
ls $(echo -e "file1
file2")
> chmod 777 tryme.sh
> ./tryme.sh
file1 file2