내 입력 파일(objects.lst)은 다음과 같습니다.
host.fqdn.com:/ 'host.fqdn.com [/]'
host.fqdn.com:/boot 'host.fqdn.com [/boot]'
host.fqdn.com:/tmp 'host.fqdn.com [/tmp]'
host.fqdn.com:/tmp '/tmp'
host.fqdn.com:/ '/usr/share'
host.fqdn.com:/var 'host.fqdn.com [/var]'
이 파일을 한 줄씩 반복하고 싶고 각 줄이 타사 소프트웨어에 대한 인수로 필요합니다.
그래서 나는 다음과 같은 것을 시도했습니다.
#!/bin/bash
set -x
while read -r line; do
/opt/report -filesystem "$line" -detail
done < objects.lst
이것은 다음과 같이 해석될 것이다.
/opt/report -filesystem 'host.fqdn.com:/ '\''host.fqdn.com [/]'\''' -detail
하지만 그래야 해
/opt/report -filesystem host.fqdn.com:/ 'host.fqdn.com [/]'
매개 변수를 배열, 변수, 다양한 참조에 저장하고 for 루프를 통해 저장하는 등 다양한 작업을 시도했지만 echo -E
원하는 방식으로 작동하는 것은 없습니다.
현재 해결 방법은 다음과 같습니다.
#!/bin/bash
set -x
while read -r line; do
echo "/opt/report -filesystem "${line}" -detail" | bash -
done < objects.lst
bash에 에코/파이핑하지 않고 작동하게 하는 또 다른 방법이 있습니까?
${parameter@Q}(bash 4.4에서 사용 가능)의 몇 가지 예를 보았지만 bash 4.2를 사용하고 있습니다.
분명히 set -x 출력을 혼동했지만 문제는 여전히 동일합니다. 저는 object.lst를 반복하고 있으며 object.lst와 정확히 동일한 전체 행이 매개변수로 필요합니다.
따라서 아래 설명을 올바르게 이해하면 다음과 같습니다.
while read -r line; do
/opt/report -filesystem "$line" -detail
done < objects.lst
이는 정확히 다음과 같아야 합니다.
/opt/report -filesystem host.fqdn.com:/ 'host.fqdn.com [/]'
그러나 그것은 진실이 아니다. 루프에서 omnidb/report에서 "객체를 찾을 수 없음"이 발생하기 때문에 타사 소프트웨어가 여기서 문제일 수 있습니다(microfocus data saver/omnidb cli 명령).
하지만 내가 만들면
while read -r line; do
echo "/opt/report -filesystem "$line" -detail"
done < objects.lst
출력 명령에서 복사/붙여넣기를 하면 정상적으로 작동하고 omnidb/report 명령에서 올바른 개체 정보를 인쇄합니다.
답변1
의 경우 /opt/report -filesystem "$line" -detail
다음 host.fqdn.com:/ 'host.fqdn.com [/]'
과 같이 그대로 전달됩니다.하나명령의 인수와 set -x
출력은 값을 작은따옴표(셸에서는 리터럴 따옴표)로 표시하여 이를 알려줍니다.
존재하다
/opt/report -filesystem host.fqdn.com:/ 'host.fqdn.com [/]'
명령에 두 개의 인수( host.fqdn.com:/
및 ) 를 전달합니다 host.fqdn.com [/]
. 이는 공백 문자와 작은따옴표 문자가 모두 쉘 구문에서 특별하기 때문입니다.
쉘의 경우 위에 '...'
표시된 대로말 그대로따옴표는 문자 그대로 텍스트를 전달하는 데 사용되며 내부 문자는 특별히 처리되지 않으며 셸 구문의 SPC(자체가 따옴표로 묶이지 않은 경우)는 인수(또는 보다 일반적으로 셸 구문의 토큰)를 구분하는 데 사용됩니다.
host.fqdn.com:/ 'host.fqdn.com [/]'
출력에 표시된 대로 문자 그대로 인수로 전달 하려면 set -x
다음과 같은 것이 필요합니다 'host.fqdn.com:/ '\''host.fqdn.com [/]'\'''
. 단, 다른 유형의 따옴표를 사용해 "host.fqdn.com:/ 'host.fqdn.com [/]'"
도 작동합니다.
$ printf '<%s>\n' 'host.fqdn.com:/ '\''host.fqdn.com [/]'\'''
<host.fqdn.com:/ 'host.fqdn.com [/]'>
$ printf '<%s>\n' "host.fqdn.com:/ 'host.fqdn.com [/]'"
<host.fqdn.com:/ 'host.fqdn.com [/]'>
이것을 명령에 전달된 리터럴 인수가 아닌 쉘 코드로 해석 해야 하는 경우 파이프와 같은 것에서 쉘 인터프리터를 호출 host.fqdn.com:/ 'host.fqdn.com [/]'
해야 합니다 (큰따옴표 사용은 올바르지 않지만) .$line
bash
eval
#!/bin/bash -
set -x
while IFS= read -r line; do
eval "/opt/report -filesystem $line -detail"
done < objects.lst
그러나 이는 행에 ;reboot;
또는 이 포함되어 있으면 $(reboot)
명령 reboot
이 호출된다는 것을 의미합니다.
다른 부작용(예: 위 명령 실행) 없이 쉘 토큰화 및 참조 제거를 수행하려는 경우 연산자와 함께 명령을 reboot
사용할 수 있습니다 .zsh
#!/bin/zsh -
set -x
while IFS= read -r line; do
/opt/report -filesystem "${(Q@)${(z)line}}" -detail
done < objects.lst
이로 z
인해 토큰화가 zsh
코드가 되고 Q
따옴표 레이어가 제거됩니다. 예를 들어, 다음과 같은 줄에서:
foo 'bar baz' $(echo x y)
foo
, bar baz
및 3개의 매개변수를 전달합니다 $(echo x y)
.
답변2
작성한 내용에 따르면 해당 행을 단일 인수로 프로그램에 전달할 필요는 없지만 두 개의 인수로 전달할 필요가 있는 것 같습니다. 행에서 인용되지 않은 부분을 하나로, 다음 인용 문자열을 다른 인수로 전달합니다. .
만약에이 모든 줄은 이 형식을 따릅니다(더 이상 인용된 문자열이 포함된 줄은 없습니다). Bash에서 다음과 같은 작업을 수행할 수 있습니다.
#/bin/bash
while IFS=" " read -r a b; do
b=${b%\'};
b=${b#\'};
/opt/report -filesystem "$a" "$b" -detail
done < objects.lst
첫 번째 공간에서 라인을 두 부분으로 나누고 그 부분을 sum read
에 저장합니다 . 그런 다음 작은따옴표가 제거되고 두 문자열이 모두 다른 인수로 에 전달됩니다 .a
b
b=${b%\'}; b=${b#\'};
/opt/report