Bash에서 파이프가 값을 설정하지 않은 후에 읽습니다.

Bash에서 파이프가 값을 설정하지 않은 후에 읽습니다.

ksh의 경우 값을 구분하기 위한 편의 방법으로 read를 사용합니다.

$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a 
2 1
$

하지만 Bash에서는 실패합니다.

$ echo 1 2 3 4 5 | read a b dump
$ echo $b $a 
  
$

매뉴얼 페이지에서 실패 이유를 찾지 못했습니다. 어떤 아이디어가 있습니까?

답변1

bash 파이프라인의 오른쪽을 실행합니다.안에서브쉘 컨텍스트, 따라서 변수에 대한 변경 사항(완료된 작업 read)은 유지되지 않습니다. 명령이 끝날 때 하위 쉘이 저장되면 사라집니다.

대신에 다음을 사용할 수 있습니다.프로세스 교체:

$ read a b dump < <(echo 1 2 3 4 5)
$ echo $b $a
2 1

이 경우 read기본 셸에서 실행되고 출력 생성 명령은 하위 셸에서 실행됩니다. <(...)문법만들다read서브쉘을 만들고 출력을 파이프에 연결하여 일반 입력으로 리디렉션합니다.<작업. read메인 셸에서 실행 중이므로 변수가 올바르게 설정되었습니다 .

주석에서 지적했듯이 실제로 문자열을 어떻게든 변수로 분할하는 것이 목표라면 다음을 사용할 수 있습니다.여기에 있는 문자열:

read a b dump <<<"1 2 3 4 5"

할 일이 더 있다고 생각하지만 그렇지 않다면 이것이 더 나은 선택입니다.

답변2

이는 사용자가 관찰한 불행한 차이를 초래하는 권한 및 동작 bash으로 인한 버그 가 아닙니다 .POSIXbashksh

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_12

또한 다중 명령 파이프라인의 각 명령은 하위 셸 환경에 있지만 확장으로 파이프라인의 일부 또는 모든 명령을 현재 환경에서 실행할 수 있습니다. 다른 모든 명령은 현재 쉘 환경 내에서 실행되어야 합니다.

그러나 bash 4.2최신 버전 에서는 lastpipe비대화형 스크립트에서 이 옵션을 설정하여 예상된 결과를 얻을 수 있습니다. 예를 들면 다음과 같습니다.

#!/bin/bash

echo 1 2 3 4 5 | read a b dump
echo before: $b $a 
shopt -s lastpipe
echo 1 2 3 4 5 | read a b dump
echo after: $b $a 

산출:

before:
after: 2 1

관련 정보