programing

여러 줄 출력을 Bash 변수로 캡처

goodcopy 2023. 4. 8. 11:50
반응형

여러 줄 출력을 Bash 변수로 캡처

다음을 출력하는 스크립트 'myscript'가 있습니다.

abc
def
ghi

다른 스크립트에서는, 다음과 같이 전화합니다.

declare RESULT=$(./myscript)

★★★★★★★★★★★★★★★★★」$RESULT를 얻다

abc def ghi

로 저장하여 '\n'자로할 수 요?echo -e

실제로 결과에는 다음과 같은 내용이 포함되어 있습니다.

echo "$RESULT"

표시되는 내용은 다음과 같습니다.

echo $RESULT

되어 있듯이그는 (1) 버전( 「」 「」 「」, 「」(1) 「」 「」입니다.echo "$RESULT"는 변수에 간격(탭, 등)을 (2) 가 없는 버전()은 따옴표가 없는 버전 「」, 「」, 「」, 「」, 「」, 「」, 「」, 「」, 「」(2개)echo $RESULT 탭 및의 각 는 하나 이상의 공백, 탭 및 줄바꿈의 각 시퀀스를 1개의 공백으로 바꿉니다.따라서 (1) 입력 변수의 모양을 유지하는 반면 (2)는 단일 공백으로 구분된 'words'로 잠재적으로 매우 긴 단일 출력 행을 생성합니다(여기서 'word'는 공백이 아닌 문자의 시퀀스입니다. 어떤 단어에도 영숫자가 있을 필요는 없습니다).

또 하나의 함정은 명령어 대체입니다.$(): 후행의 줄바꿈을 삭제합니다.항상 중요한 것은 아니지만 출력된 내용을 그대로 유지하려면 다른 행과 인용문을 사용해야 합니다.

RESULTX="$(./myscript; echo x)"
RESULT="${RESULTX%x}"

이는 가능한 모든 파일 이름처리하는 경우(잘못된 파일에서 작업하는 것과 같은 정의되지 않은 동작을 방지하기 위해) 특히 중요합니다.

특정 행에 관심이 있는 경우 result-array를 사용합니다.

declare RESULT=($(./myscript))  # (..) = array
echo "First line: ${RESULT[0]}"
echo "Second line: ${RESULT[1]}"
echo "N-th line: ${RESULT[N]}"

@l0b0의 답변에 더해 스크립트에 의해 출력되는 후행 뉴라인을 유지하고 스크립트의 리턴 코드를 확인해야 하는 상황이 있었습니다.그리고 l0b0의 답변의 문제는 '에코 x'가 $?를 0으로 재설정하고 있었다는 것이다.그래서 저는 아주 교활한 해결책을 생각해냈습니다.

RESULTX="$(./myscript; echo x$?)"
RETURNCODE=${RESULTX##*x}
RESULT="${RESULTX%x*}"

다중 출력 구문 분석

서론

당신의 ★★★★★★★★★★★★★★★★★★★.myscript3번, 3번, 3번, 3번, 3번.

myscript() { echo $'abc\ndef\nghi'; }

또는

myscript() { local i; for i in abc def ghi ;do echo $i; done ;}

OK는 )../ 아, 아, 아, 아, 아, 아, 아, 아, 아, 아, 아.

myscript
abc
def
ghi

결과코드참조

결과 코드를 확인하기 위해 테스트 기능은 다음과 같습니다.

myscript() { local i;for i in abc def ghi ;do echo $i;done;return $((RANDOM%128));}

1. 여러 출력을 하나의 변수에 저장하여 새로운 라인을 표시하다

조작이 올바릅니다.

RESULT=$(myscript)

결과 코드에 대해 다음을 추가할 수 있습니다.

RCODE=$?

같은 행이라도:

RESULT=$(myscript) RCODE=$?

그리고나서

echo $RESULT $RCODE
abc def ghi 66
echo "$RESULT"
abc
def
ghi
echo ${RESULT@Q}
$'abc\ndef\nghi'
printf '%q\n' "$RESULT"
$'abc\ndef\nghi'

그러나 변수 정의를 표시하려면declare -p:

declare -p RESULT RCODE
declare -- RESULT="abc
def
ghi"
declare -- RCODE="66"

2. 어레이 내의 여러 출력 해석, 사용mapfile

답변 저장처myvar변수:

mapfile -t myvar < <(myscript)
echo ${myvar[2]}
ghi

표시하다$myvar:

declare -p myvar
declare -a myvar=([0]="abc" [1]="def" [2]="ghi")

결과코드참조

결과 코드를 확인해야 하는 경우 다음을 수행할 수 있습니다.

RESULT=$(myscript) RCODE=$?
mapfile -t myvar <<<"$RESULT"

declare -p myvar RCODE
declare -a myvar=([0]="abc" [1]="def" [2]="ghi")
declare -- RCODE="40"

3. 복수 출력의 연속 해석read명령어 그룹 내

{ read firstline; read secondline; read thirdline;} < <(myscript)
echo $secondline
def

변수 표시:

declare -p firstline secondline thirdline
declare -- firstline="abc"
declare -- secondline="def"
declare -- thirdline="ghi"

자주 사용하는 항목:

{ read foo;read foo total use free foo ;} < <(df -k /)

그리고나서

declare -p use free total
declare -- use="843476"
declare -- free="582128"
declare -- total="1515376"

결과코드참조

동일한 선행 절차:

RESULT=$(myscript) RCODE=$?
{ read firstline; read secondline; read thirdline;} <<<"$RESULT"

declare -p firstline secondline thirdline RCODE
declare -- firstline="abc"
declare -- secondline="def"
declare -- thirdline="ghi"
declare -- RCODE="50"

여기서 대부분의 솔루션을 사용해 본 결과, 가장 쉬운 것은 temp 파일을 사용하는 것입니다.여러 줄 출력으로 무엇을 하고 싶은지 잘 모르겠지만, 읽기를 사용하여 한 줄씩 처리할 수 있습니다.실제로 할 수 없는 유일한 것은 모든 것을 같은 변수에 쉽게 고정시키는 것이지만, 대부분의 실용적인 목적을 위해서는 이 모든 것을 훨씬 쉽게 처리할 수 있습니다.

./myscript.sh > /tmp/foo
while read line ; do 
    echo 'whatever you want to do with $line'
done < /tmp/foo

빠른 해킹을 통해 요청된 작업을 수행할 수 있습니다.

result=""
./myscript.sh > /tmp/foo
while read line ; do
  result="$result$line\n"
done < /tmp/foo
echo -e $result

이렇게 하면 행이 추가됩니다.네가 작업하면 코드도 쓸 수 있어, 난 그냥 너무 게을러.


편집: 이 케이스는 완벽하게 동작하지만, 이 케이스를 읽는 사람들은 당신이 당신의 stdin을 while loop 안에 쉽게 찌그러뜨릴 수 있다는 것을 알아야 합니다.그러면 당신은 당신에게 한 줄을 실행하고 stdin을 클리어하고 종료하는 스크립트를 줄 수 있습니다.내 생각엔 ssh가 그렇게 할 것 같아?최근에 확인했습니다.다른 코드 예는 https://unix.stackexchange.com/questions/24260/reading-lines-from-a-file-with-bash-for-vs-while 입니다.

한 번 더!이번에는 다른 파일 핸들(stdin, stdout, stderr이 0-2이므로 bash에서 &3 이상을 사용할 수 있습니다).

result=""
./test>/tmp/foo
while read line  <&3; do
    result="$result$line\n"
done 3</tmp/foo
echo -e $result

mktemp도 사용할 수 있지만 이것은 간단한 코드 예시입니다.mktemp의 사용법은 다음과 같습니다.

filenamevar=`mktemp /tmp/tempXXXXXX`
./test > $filenamevar

그런 다음 파일의 실제 이름과 마찬가지로 $filenamevar를 사용합니다.아마 여기에 설명이 필요없을 텐데 댓글에 어떤 분이 불평을 하시네요.

이것은 어떻습니까? 각 행을 변수에 읽어들이고 나중에 사용할 수 있습니다! myscript 출력은 myscript_output이라는 파일로 리다이렉트 됩니다.

awk '{while ( (getline var < "myscript_output") >0){print var;} close ("myscript_output");}'

언급URL : https://stackoverflow.com/questions/613572/capturing-multiple-line-output-into-a-bash-variable

반응형