我想从命令行读取一些字符串并在 loo 中读取所有字符串。如何在循环中进一步处理(如打印)它们。对不起,我是新手,请原谅我的新手问题。
#!/usr/bin/bash
echo "Enter the number of names of students"
read classcount
for ((i=1;i<=classcount;i++)); do
read names[${i}]
done
for ((i=1;i<=classcount;i++)); do
echo $names[${i}]
done
Run Code Online (Sandbox Code Playgroud)
通常,最好避免脚本中的用户交互或从命令行使用的任何实用程序,因为它会阻碍自动化。
例如,您调用rm file1 file2 'file 3',而不rm只是期望它询问您要删除的文件数,然后分别提示每个文件。
同样,在这里,从命令行参数中获取学生列表会好得多:
#! /usr/bin/bash -
classcount=$#
names=("$@")
if (( classcount > 0 )); then
echo "Student${name[1]+s}:"
printf ' - %s\n' "${name[@]}"
fi
Run Code Online (Sandbox Code Playgroud)
并调用为:
that-script 'John Doe' 'Alice Smith' ...
Run Code Online (Sandbox Code Playgroud)
或者,例如从文本文件中每行获取一个学生列表(假设为 GNU xargs):
xargs -d '\n' -a student.list that-script
Run Code Online (Sandbox Code Playgroud)
您也可以从标准输入中每行读取一个,但最好没有交互并阅读列表直到输入结束,而不是先提示用户进行计数:
#! /usr/bin/bash -
readarray -t names
classcount="${#names[@]}"
if (( classcount > 0 )); then
echo "Student${name[1]+s}:"
printf ' - %s\n' "${name[@]}"
fi
Run Code Online (Sandbox Code Playgroud)
如果 stdin 是终端,则用户将用 表示输入结束Ctrl+D。
要从文件中获取列表:
that-script < student.list
Run Code Online (Sandbox Code Playgroud)
read可用于从 stdin 读取一行,但语法是IFS= read -r lvalue,而不是read lvalue。
另请注意,这[...]是一个通配符,因此应该被引用以及出现在列表上下文中的所有参数扩展。
此外,数组索引(除了"$@"Bourne 数组)在bashlike in ksh(但与大多数其他 shell 不同)中,从 0 开始,而不是 1。
因此,对于您的方法,语法应该是:
#! /usr/bin/bash -
PROGNAME=$0
die() {
(( $# == 0 )) || printf >&2 '%s: ERROR: %s\n' "$PROGNAME" "$1"
exit 1
}
IFS= read -rp "Enter the number of names of students: " classcount || die
# validate to avoid command injection vulnerability
shopt -s extglob # only needed in older versions of bash
[[ $classcount = @(0|[123456789]*([0123456789])) ]] ||
die "Not a valid decimal integer number: $classcount"
for (( i = 1; i <= classcount; i++ )); do
IFS= read -rp "Student $i: " 'names[i-1]' ||
die "$(( classcount - i + 1 )) students missing"
done
for (( i=1; i <= classcount; i++)); do
printf 'Student %s: %s\n' "$i" "${names[i-1]}"
done
Run Code Online (Sandbox Code Playgroud)
$name[$i]在 (t)csh(70 年代末首次引入数组的 shell)中是有效的,尽管您需要$name[$i]:q确保空格或通配符在它们中或在 zsh 中不被特殊处理,但不是在bash其中复制的ksh' s 阵列设计。
在这方面,ksh 努力与 Bourne shell 向后兼容,因此echo $name[$i]会像在 Bourne shell 中一样输出与<contents-of-$name>[<contents-of-$i>]模式匹配的文件列表($name并且$i也会受到拆分)。
在 ksh/bash 中,您需要${name[i]}语法(${name[$i]}或${name[${i}]}也可以使用),并且对于每个参数扩展,请确保将其引用 ( "${name[i]}") 以防止 split+glob。
在任何情况下,echo都不能用于输出任意数据。