为什么 cut 命令不拆分给定的字符串?

sea*_*fab 0 echo cut

在这里按预期剪切工作

$ cat test 
1;2;3;4
$ cut -d ';' -f 2 test 
2
$ cut -d ';' -f 3 test 
3
Run Code Online (Sandbox Code Playgroud)

但我希望它在这里输出“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
Run Code Online (Sandbox Code Playgroud)

当我尝试 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
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 5

要将命令的标准输出和标准错误(减去尾随换行符)分配给变量,类 POSIX 外壳中的语法是:

updates=$(/usr/lib/update-notifier/apt-check 2>&1)
Run Code Online (Sandbox Code Playgroud)

要使用添加的换行符输出变量的内容,语法为:

printf '%s\n' "$updates"
Run Code Online (Sandbox Code Playgroud)

要在字符上拆分变量的内容,语法是:

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

printf '%s\n' "First element: $1" "Second element: $2"
Run Code Online (Sandbox Code Playgroud)

或者你可以这样做:

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"
Run Code Online (Sandbox Code Playgroud)

获得相当于

/usr/lib/update-notifier/apt-check --human-readable
Run Code Online (Sandbox Code Playgroud)

您还可以使用以下cut命令获取变量每一行的第一个分号分隔字段:

printf '%s\n' "$updates" | cut -d ';' -f 1
Run Code Online (Sandbox Code Playgroud)

尽管如果该变量只有一行,那就有点矫枉过正了。