cut 명령이 주어진 문자열을 분할하지 않는 이유는 무엇입니까?

cut 명령이 주어진 문자열을 분할하지 않는 이유는 무엇입니까?

여기서 컷은 예상대로 작동합니다.

$ cat test 
1;2;3;4
$ cut -d ';' -f 2 test 
2
$ cut -d ';' -f 3 test 
3

하지만 여기서는 "21"을 출력하고 싶습니다. 제가 뭘 잘못하고 있는 걸까요?

$ updates=""
$ echo "$updates" | cat -v

$ updates=$(/usr/lib/update-notifier/apt-check 2>&1);echo $updates
21;0
$ echo "$updates" | cat -v
21;0
$ updates=""
$ updates=$(/usr/lib/update-notifier/apt-check 2>&1);echo $updates | 
cut -d ";" -f 1
21
$ echo "$updates" | cat -v
21;0

Stéphanes 솔루션을 사용해 보면

$ cat test2.sh 
updates=$(/usr/lib/update-notifier/apt-check)
all=${updates%";"*}
security=${updates#*";"}
printf '%s\n' "$all packages can be updated" \
          "$security updates are security updates"
$ ./test2.sh 
21;0 packages can be updated
updates are security updates

답변1

명령의 표준 출력 및 표준 오류(후행 줄 바꿈 제외)를 변수에 할당하려면 POSIX와 유사한 셸의 구문은 다음과 같습니다.

updates=$(/usr/lib/update-notifier/apt-check 2>&1)

개행 문자가 추가된 변수의 내용을 출력하려면 구문은 다음과 같습니다.

printf '%s\n' "$updates"

변수의 내용을 문자로 분할하는 구문은 다음과 같습니다.

IFS=';'
set -o noglob
set -- $updates

printf '%s\n' "First element: $1" "Second element: $2"

아니면 이렇게 할 수도 있습니다:

updates=$(/usr/lib/update-notifier/apt-check 2>&1)
all=${updates%";"*}
security=${updates#*";"}
printf '%s\n' "$all packages can be updated" \
              "$security updates are security updates"

동등한 것을 얻으려면

/usr/lib/update-notifier/apt-check --human-readable

cut다음을 사용하여 변수 각 줄의 첫 번째 세미콜론으로 구분된 필드를 가져올 수도 있습니다 .

printf '%s\n' "$updates" | cut -d ';' -f 1

그러나 변수에 행이 하나만 있으면 과잉입니다.

관련 정보