在 while 循环 bash 脚本中读取文件
Reading file in while loop bash scripting
我有这段代码可以读取 /etc/passwd:
的示例文件
#!/bin/bash
OLDIFS=$IFS
IFS=$'\n'
while read linea resto
do
echo $linea
echo $resto
if [[ $(echo $linea | cut -d: -f6 | egrep -c 'al-03-04') == 1 ]]
then
finger $(cut -d: -f1) 2> fich
if [[ $(egrep -c fich) == 1 ]]
then
echo $(echo $linea | cut -d: -f1). Inactive user
else
echo $(echo $linea | cut -d: -f1). Active user
fi
fi
done < <(cat fichpasswd)
IFS=$OLDIFS
这是/etc/passwd的示例文件:
jfer:x:5214:1007:Javier Lopez,,,:/home/al-03-04/jfer:/bin/bash
jperez:x:10912:1009:Juan Perez,,,:/home/al-03-04/jperez:/bin/bash
mfernan:x:10913:1009:Manuel Fernandez,,,:/home/al-02-03/mfernan:/bin/bash
问题是 while 循环只读取第一行,忽略其他行。脚本的输出是:
jfer:x:5214:1007:Javier Lopez,,,:/home/al-03-04/jfer:/bin/bash
jfer. Active user
您可以尝试类似的方法:
#!/bin/bash
FILE="test.txt"
while IFS=":" read -a data; do
echo "${data[@]}"
if [[ $(echo ${data[5]}|egrep -c 'al-03-04') -eq 1 ]]; then
if [[ $(finger "${data[0]}" 2>&1) =~ "no such user" ]]; then
echo "${data[0]}. Inactive user"
else
echo "${data[0]}. Active user"
fi
fi
done < "$FILE"
这是输出:
ineumann ~ $ cat test.txt
ineumann:x:5214:1007:Javier Lopez,,,:/home/al-03-04/jfer:/bin/bash
jperez:x:10912:1009:Juan Perez,,,:/home/al-03-04/jperez:/bin/bash
mfernan:x:10913:1009:Manuel Fernandez,,,:/home/al-02-03/mfernan:/bin/bash
ineumann ~ $ ./test.sh
ineumann x 5214 1007 Javier Lopez,,, /home/al-03-04/jfer /bin/bash
ineumann. Active user
jperez x 10912 1009 Juan Perez,,, /home/al-03-04/jperez /bin/bash
jperez. Inactive user
mfernan x 10913 1009 Manuel Fernandez,,, /home/al-02-03/mfernan /bin/bash
对您的脚本的一些评论:
- 无需使用
cat
循环读取文件。
finger $(cut -d: -f1) 2> fich
: cut
需要输入。并且不需要使用临时文件来捕获 finger
的输出(而且这不是线程安全的)。
- 当您选择正确的
IFS
将一行拆分为多个部分时,无需在脚本中使用 cut
。对于您的情况,我认为最明智的选择是 :
.
- 您只能在循环内使用语法
while IFS=':' read; do ...; done
更改 IFS
。无需重新分配 IFS
与 OLDIFS
.
- 您还可以使用
while IFS=':' read var1 var2 var3 trash; do ...; done
语法来避免将数组与 read -a
一起使用(但我更愿意使用我在您的脚本版本中所写的数组)。
我有这段代码可以读取 /etc/passwd:
的示例文件#!/bin/bash
OLDIFS=$IFS
IFS=$'\n'
while read linea resto
do
echo $linea
echo $resto
if [[ $(echo $linea | cut -d: -f6 | egrep -c 'al-03-04') == 1 ]]
then
finger $(cut -d: -f1) 2> fich
if [[ $(egrep -c fich) == 1 ]]
then
echo $(echo $linea | cut -d: -f1). Inactive user
else
echo $(echo $linea | cut -d: -f1). Active user
fi
fi
done < <(cat fichpasswd)
IFS=$OLDIFS
这是/etc/passwd的示例文件:
jfer:x:5214:1007:Javier Lopez,,,:/home/al-03-04/jfer:/bin/bash
jperez:x:10912:1009:Juan Perez,,,:/home/al-03-04/jperez:/bin/bash
mfernan:x:10913:1009:Manuel Fernandez,,,:/home/al-02-03/mfernan:/bin/bash
问题是 while 循环只读取第一行,忽略其他行。脚本的输出是:
jfer:x:5214:1007:Javier Lopez,,,:/home/al-03-04/jfer:/bin/bash
jfer. Active user
您可以尝试类似的方法:
#!/bin/bash
FILE="test.txt"
while IFS=":" read -a data; do
echo "${data[@]}"
if [[ $(echo ${data[5]}|egrep -c 'al-03-04') -eq 1 ]]; then
if [[ $(finger "${data[0]}" 2>&1) =~ "no such user" ]]; then
echo "${data[0]}. Inactive user"
else
echo "${data[0]}. Active user"
fi
fi
done < "$FILE"
这是输出:
ineumann ~ $ cat test.txt
ineumann:x:5214:1007:Javier Lopez,,,:/home/al-03-04/jfer:/bin/bash
jperez:x:10912:1009:Juan Perez,,,:/home/al-03-04/jperez:/bin/bash
mfernan:x:10913:1009:Manuel Fernandez,,,:/home/al-02-03/mfernan:/bin/bash
ineumann ~ $ ./test.sh
ineumann x 5214 1007 Javier Lopez,,, /home/al-03-04/jfer /bin/bash
ineumann. Active user
jperez x 10912 1009 Juan Perez,,, /home/al-03-04/jperez /bin/bash
jperez. Inactive user
mfernan x 10913 1009 Manuel Fernandez,,, /home/al-02-03/mfernan /bin/bash
对您的脚本的一些评论:
- 无需使用
cat
循环读取文件。 finger $(cut -d: -f1) 2> fich
:cut
需要输入。并且不需要使用临时文件来捕获finger
的输出(而且这不是线程安全的)。- 当您选择正确的
IFS
将一行拆分为多个部分时,无需在脚本中使用cut
。对于您的情况,我认为最明智的选择是:
. - 您只能在循环内使用语法
while IFS=':' read; do ...; done
更改IFS
。无需重新分配IFS
与OLDIFS
. - 您还可以使用
while IFS=':' read var1 var2 var3 trash; do ...; done
语法来避免将数组与read -a
一起使用(但我更愿意使用我在您的脚本版本中所写的数组)。