2017-02-16 44 views
0

我有一个包含两列(名称和ID)的文件。使用BASH,我想通读文件的所有行并将每列分配给一个变量$ name和$ ID。这些列由空格分隔,我想确保在文件中包含最后一行。有人可以帮忙吗?将文件中的两列读入BASH中的变量

+0

**请添加**一些你有什么样的例子和你想要的结果。 –

回答

1

您的问题可能是,最后一行是不是在while read循环处理,如果不换行结束:

printf '%s %s\n%s %s' a b c d | while read x y ; do 
    printf '%s, %s\n' $x $y 
done 

您可以添加新行通过下面的Perl oneliner例如线:

perl -pe '$_ .= "\n" unless /\n/' 

它将换行添加到没有一行的行,它必须是最后一行。

检查:

printf '%s %s\n%s %s' a b c d \ 
| perl -pe '$_ .= "\n" unless /\n/' \ 
| while read x y ; do 
    printf '%s, %s\n' $x $y 
done 

如果你正在处理多个文件,只是处理它们第一次换行添加到每个的最后一行:

perl -pe '$_ .= "\n" unless /\n/' -- files* | while read x y ; do ... 
+0

管道进入'while read'意味着在那里设置的变量不会被持久化 - 正如你所知道的那样。也应适当引用。我强烈建议'||作为修改输入流的替代方法,如果成功地填充了至少一个变量,即使在非零退出状态的读取之后,[[$ x]]也可以执行循环。 –

+0

@CharlesDuffy:或者这个技巧很不错,将它添加为答案。 – choroba

+0

(re:“也应该适当引用” - 是的,因为'read'是使用继承的IFS,我们知道'x'不会包含任何相同的字符,但'''可以,并且还有可能存在小块在场)。 –

1

为了确保循环,即使之后运行解析无效行(例如文件末尾没有尾随换行符的行),如果读取任何数据,则可以使用备用测试指示成功:

while read -r name id _ || [[ $name ]]; do 
    printf 'Read name: %s, and id: %s\n' "$name" "$id" 
done <input 

在这里,我们检查$name是否为非空,如果read报告失败,并继续运行循环的主体(如果发生的话)。变量“吸取”列3和以后,只读出前两个。


因为这种方法不依赖于管道,你可以放心的是,在循环中设置的变量都坚持过去的退出:

name_count=0 
while read -r name id _ || [[ $name ]]; do 
    name_count=$((name_count+1)) 
    printf 'Read name: %s, and id: %s\n' "$name" "$id" 
done <input 
echo "Read a total of $name_count names" 

否则,可能会发生冲突的BashFAQ #24运行(”我在流水线中的循环中设置变量,为什么它们在循环终止后消失?或者,为什么我不能通过管道数据读取?“)。

相关问题