使用read、IFS和while一起的疑惑

使用read、IFS和while一起的疑惑

我有疑问,因为我明白:

exec 0</etc/passwd
IFS=:
while read in USUARIO
do
    echo $USUARIO
done

输出应该是包含所有系统用户的列表,而不是当我想要第一行时,我会得到第二行,其中填充了 x;为什么?

此外,在此脚本中,您传递一个数字作为参数,您会看到拥有与输入值相同且更多文件的用户列表:

#!/bin/bash

if [[ ( $# -eq 1) && ( $1==[0-9][0-9]* )]]
then
    echo "User with $1 files or more "
    cut -d':' -f1 /etc/passwd | while IFS= read -r USUARIO
    do
        if [[ $( find / -user $USUARIO -print | wc -l ) -ge $1 ]]
        then

            echo $USUARIO
        fi
    done
exit 0
else
    printf "Error: $0 int"
    exit 1
fi

它工作正常,但为什么它不起作用:

#!/bin/bash

if [[ ( $# -eq 1) && ( $1==[0-9][0-9]* )]]
then
    LIST="Users with more or $1 files: "
    cut -d':' -f1 /etc/passwd | while IFS= read -r USUARIO
    do
        if [[ $( find / -user $USUARIO -print | wc -l ) -ge $1 ]]
        then

            LIST="$LIST $USUARIO"
        fi
    done
echo $LIST
exit 0
else
    printf "Error $0 int"
    exit 1
fi

它的输出是原始字符串,没有附加用户名,为什么?

答案1

您似乎混淆了forand的语法whilefor对列表中的每个元素执行一系列命令;语法是:关键字将变量名与值列表分开。当另一个命令序列为真时执行一个命令序列;语法是.for VARIABLE in VALUES; do COMMANDS; doneinwhilewhile COMMANDS; do COMMANDS; done

该命令read读取一行并将其拆分为多个字段。的参数read是要设置字段值的变量。因此,read in USUARIO设置in为第一个字段和USUARIO第二个字段,或者如果有两个以上字段(您的场景中就是这种情况),则USUARIO设置为所有剩余字段(包括内部分隔符)。每次调用都会read读取一行,因此每次循环迭代都会处理一行输入。

因此,要仅打印用户名,您需要编写

while IFS=: read USUARIO rest
do
    echo "$USUARIO"
done

关于第二个问题(但下次请不要一起问不相关的问题),问题是管道中的每个命令都是在子shell中执行的,因此其中一个命令中设置的变量在管道外部不可见。看为什么我的变量是本地一个“while read”循环,而不是另一个看似类似的循环?

相关内容