이 명령은 df .
현재 사용 중인 장치를 표시합니다. 예를 들어,
me@ubuntu1804:~$ df .
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sdb1 61664044 8510340 49991644 15% /home
이제 문자열을 얻고 싶습니다 /dev/sdb1
.
이 작업을 시도했지만 작동하지 않습니다. df . | read a; read a b; echo "$a"
이 명령은 빈 출력을 제공합니다. 하지만 df . | (read a; read a b; echo "$a")
예상대로 작동합니다.
지금은 조금 혼란스러워요.
이것이 서브쉘이라는 것은 알지만 (read a; read a b; echo "$a")
왜 여기서 서브쉘을 만들어야 하는지 모르겠습니다. 내가 이해하는 바에 따르면 의 출력은 의 입력으로 x|y
리디렉션됩니다 . 왜 나는 입력을 받을 수 없는데 서브셸에서는 입력을 받을 수 있나요?x
y
read a; read a b; echo $a
답변1
여기서 가장 중요한 문제는 명령을 올바르게 그룹화하는 것입니다. 서브쉘은 사소한 문제입니다.
x|y
x
출력을 입력으로 리디렉션y
예, 하지만 출력을 에서 또는 으로 x | y; z
리디렉션하지 않습니다 .x
y
z
에서는 df . | read a; read a b; echo "$a"
파이프가 연결만 되고 df .
다른 read a
명령은 이 파이프와 연결되지 않습니다. read
그것들을 함께 그룹화 df . | { read a; read a b; }
하거나 df . | (read a; read a b)
파이프를 연결 해야 합니다 .
그러나 이제 하위 셸 문제가 발생했습니다. 파이프라인의 명령이 하위 셸에서 실행되므로 하위 셸에 변수를 설정해도 상위 셸에 영향을 주지 않습니다. 따라서 이 echo
명령은 read
s와 동일한 하위 쉘에 있어야 합니다. 그래서: df . | { read a; read a b; echo "$a"; }
.
이제 파이프의 명령은 어쨌든 서브셸에서 실행되므로 사용 여부 ( ... )
에 특별한 차이가 없습니다 .{ ...; }
답변2
또 다른 방법은프로세스 교체:
{ read header; read filesystem rest; } < <(df .)
echo "$filesystem"
프로세스 교체는 포함된 스크립트(하위 쉘에 있음)를 실행하지만 파일 이름처럼 작동하므로 먼저 내용(즉, 스크립트의 출력)을 중괄호 스크립트로 리디렉션 <(...)
해야 합니다 . <
그룹화된 명령은 현재 쉘에서 실행됩니다.
읽기 쉽게 만드는 것은 어려울 수 있지만 중괄호와 절차적 대체에 임의의 공백을 넣을 수 있습니다.
{
read header
read filesystem rest
} < <(
df .
)
echo "$filesystem"
외부 도구를 사용하여 파일 시스템을 추출하는 것이 더 쉬울 수 있습니다.
filesystem=$( df . | awk 'NR == 2 {print $1}' )
답변3
첫 번째 명령
df . | read a; read a b; echo "$a"
실제로는 다음과 같이 해석된다.
( df . | read a ) ; read a b; echo "$a"
따라서 파이프는 read a
명령만 입력합니다.
파이프에서 여러 번 읽기를 원하므로 명령을 그룹화해야 합니다.
이제 서브쉘일 필요는 없습니다. 단체일수도..
bash-4.2$ df | { read a ; read a b ; echo $a ; }
devtmpfs
더 일반적으로 루프가 필요할 수 있습니다.
bash-4.2$ df | while read a
> do
> read a b
> echo $a
> done
devtmpfs
tmpfs
/dev/vda3
/dev/vdb
bash
파이프 오른쪽이 서브쉘을 실행하고 있어서 루프 외부에서는 값에 접근 $a
$b
할 수 없다는 사소한 문제도 있지만 while
그건 다른 문제입니다!