bash에서 서브셸을 생성하는 동안? [복사]

bash에서 서브셸을 생성하는 동안? [복사]

누군가 이 스크립트가 내가 기대하는 결과를 생성하지 않는 이유를 설명할 수 있습니까?

 #!/bin/bash
 #

var=0

ls -1 /tmp| while read file
do
     echo $file
     var=1
done

echo "var is $var"

파일 목록을 얻은 다음var is 0

var가 1이 아닌 이유는 무엇입니까? while 루프가 하위 쉘을 생성하기 때문입니까?

답변1

파이프는 그렇습니다. 예를 들어 $BASHPIDwhile 루프 내부와 외부에서 인쇄 하거나 다음을 수행하여 직접 확인할 수 있습니다 .

ls | while read file; do
    sleep 100;
done

, 중지 C-Z하고 나중에 터미널 세션에서 프로세스 트리를 확인 ps하거나 봅니다.ps --forest

약간 다른 "파이프라인"을 통해 서브쉘을 방지할 수 있습니다.

var=0
while read file
do 
  echo $file; var=1
done < <(ls -1 /tmp/)

echo $var #=> 1

답변2

다른 좋은 답변에서는 이미 변수 값을 유지하지 않는 이유를 설명했습니다. 원한다면 이 주제에 대한 흥미로운 기사를 읽을 수 있습니다.파이프라인 내의 루프에 변수를 설정했습니다. 루프가 끝나면 왜 사라지나요? 아니면 파이프를 통해 데이터를 읽을 수 없는 이유는 무엇입니까?.

ls나는 단지 구문 분석이 전혀 필요하지 않도록 파일을 반복하는 다른 방법을 보여주고 싶었습니다 .

for file in /tmp/*
do
   echo "$file"
   var=1
done

그게 다야! /tmp/*Expand에게 디렉토리의 모든 내용을 제공하도록 요청하면 됩니다 /tmp.

귀하의 스크립트는 실제 코드가 아닌 더미 코드인 것 같습니다. 그러나 특정 값이 포함되어 있는지 확인하고 싶다면 /tmp다음과 같이 말할 수도 있습니다.

shopt -s nullglob
r=(/tmp/*)

그런 다음 배열의 요소 수를 계산합니다.

echo ${#r[@]}

이 패턴과 일치하는 항목이 없으면 리터럴 문자열로의 확장을 shopt -s nullblog차단 하곤 했습니다./tmp/*/tmp/*

답변3

while아니요, 하지만 파이프는 그렇습니다. 따라서 while예제는 서브셸에서 실행됩니다.

for반복할 목록을 생성하는 명령이 루프가 아닌 하위 쉘에서 실행되는 루프를 사용하여 동일한 작업을 수행할 수 있는 경우가 많습니다 . 예를 들어:

for file in /tmp/*; do
    echo "$file"
    var=1
done

관련 정보