【发布时间】:2012-06-07 12:36:19
【问题描述】:
我已经阅读了this question 关于如何使用 bash 从文本文件中读取 n 个字符的信息。我想知道如何从文件中一次读取一个单词:
example text
example1 text1
example2 text2
example3 text3
谁能给我解释一下,或者给我一个简单的例子? 谢谢!
【问题讨论】:
标签: bash
我已经阅读了this question 关于如何使用 bash 从文本文件中读取 n 个字符的信息。我想知道如何从文件中一次读取一个单词:
example text
example1 text1
example2 text2
example3 text3
谁能给我解释一下,或者给我一个简单的例子? 谢谢!
【问题讨论】:
标签: bash
read 命令默认读取整行。所以解决方案可能是读取整行,然后将其拆分为空格,例如for:
#!/bin/sh
while read line; do
for word in $line; do
echo "word = '$word'"
done
done <"myfile.txt"
【讨论】:
read 从标准输入读取。解决它的“最佳”方法(IMO)是将代码放入函数中。而且由于函数可以像任何其他命令一样被调用,它也可以与重定向一起使用。那么你可以做例如function_with_read_loop < some_file.
* 作为独立元素,您将从for word in $line 获得当前目录中的文件名列表。 (另外,没有-r 的read 将使用反斜杠文字)。
使用标准输入执行此操作的方法是将-a 标志传递给读取:
read -a words
echo "${words[@]}"
这会将您的整行读入索引数组变量,在本例中名为 words。然后,您可以使用 shell parameter expansions 对 words 执行任何您喜欢的数组操作。
对于面向文件的操作,当前版本的 Bash 还支持映射文件built-in。例如:
mapfile < /etc/passwd
echo ${MAPFILE[0]}
无论哪种方式,数组都是要走的路。值得您花时间熟悉 Bash array syntax 以充分利用此功能。
【讨论】:
通常,您应该使用while read -r line 循环从文件中读取。为此并解析行中的单词需要在while 循环内嵌套一个for 循环。
这是一种无需嵌套循环即可工作的技术:
for word in $(<inputfile)
do
echo "$word"
done
【讨论】:
*,您将在输出中获得当前目录中的名称列表。
在给定的上下文中,单词的数量是已知的:
while read -r word1 word2 _; do
echo "Read a line with word1 of $word1 and word2 of $word2"
done
如果您想将每一行读入一个数组,read -a 会将第一个单词放入数组的元素 0,将第二个单词放入元素 1,依此类推:
while read -r -a words; do
echo "First word is ${words[0]}; second word is ${words[1]}"
declare -p words # print the whole array
done
【讨论】:
在 bash 中,只需使用空格作为分隔符 (read -d ' ')。此方法需要一些预处理以将换行符转换为空格(使用tr)并将多个空格合并为一个(使用sed):
{
tr '\n' ' ' | sed 's/ */ /g' | while read -d ' ' WORD
do
echo -n "<${WORD}> "
done
echo
} << EOF
Here you have some words, including * wildcards
that don't get expanded,
multiple spaces between words,
and lines with spaces at the begining.
EOF
此方法的主要优点是您无需担心数组语法,只需使用 for 循环即可,但无需通配符扩展。
【讨论】:
我遇到了这个问题和建议的答案,但我没有看到列出这个简单的可能解决方案:
for word in `cat inputfile`
do
echo $word
done
【讨论】:
*,您将在输出中获得当前目录中的文件列表——并且因为echo 的参数没有被引用,如果您的文件名之一拆分为包含 glob 的单词集,该 glob也会被扩展。另请参阅Why you don't read lines with for。
这也可以使用 AWK 来完成:
awk '{for(i=1;i<=NF;i++) {print $i}}' text_file
【讨论】:
您可以将xargs(读取由空格或换行符分隔的单词)和echo结合起来,每行打印一个:
<some-file xargs -n1 echo
some-command | xargs -n1 echo
这也适用于大型或慢速数据流,因为它不需要一次读取整个输入。
我用它从 SQLite 中一次读取 1 个表名,它在列布局中打印表名:
sqlite3 db.sqlite .tables | xargs -n1 echo | while read table; do echo "1 table: $table"; done
【讨论】: