在 bash 中解析 .csv 文件,而不是读取最后一行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11821979/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 02:56:22  来源:igfitidea点击:

Parsing .csv file in bash, not reading final line

bashparsingshellunixcsv

提问by kkSlider

I'm trying to parse a csv file I made with Google Spreadsheet. It's very simple for testing purposes, and is basically:

1,2
3,4
5,6

我正在尝试解析我用 Google 电子表格制作的 csv 文件。用于测试目的非常简单,基本上是:

1,2
3,4
5,6

The problem is that the csv doesn't end in a newline character so when I catthe file in BASH, I get

问题是 csv 不以换行符结尾,所以当我cat在 BASH 中文件时,我得到

MacBook-Pro:Desktop kkSlider$ cat test.csv 
1,2 
3,4 
5,6MacBook-Pro:Desktop kkSlider$ 

I just want to read line by line in a BASH script using a while loop that every guide suggests, and my script looks like this:

我只想使用每个指南建议的 while 循环在 BASH 脚本中逐行读取,我的脚本如下所示:

while IFS=',' read -r last first
do
    echo "$last $first"
done < test.csv

The output is:

输出是:

MacBook-Pro:Desktop kkSlider$ ./test.sh
1 2
3 4

Any ideas on how I could have it read that last line and echo it?

关于我如何让它读取最后一行并回应它的任何想法?

Thanks in advance.

提前致谢。

回答by paxdiablo

You can forcethe input to your loop to end with a newline thus:

您可以强制循环的输入以换行符结束,因此:

#!/bin/bash
(cat test.csv ; echo) | while IFS=',' read -r last first
do
    echo "$last $first"
done

Unfortunately, this may result in an empty line at the end of your output if the input already has a newline at the end. You can fix that with a little addition:

不幸的是,如果输入的末尾已经有换行符,这可能会导致输出末尾出现空行。你可以通过一些补充来解决这个问题:

!/bin/bash
(cat test.csv ; echo) | while IFS=',' read -r last first
do
    if [[ $last != "" ]] ; then
        echo "$last $first"
    fi
done

Another method relies on the fact that the values are being placedinto the variables by the readbut they're just not being output because of the whilestatement:

另一种方法依赖于这样一个事实,即值被放入变量中,read但由于以下while语句,它们没有被输出:

#!/bin/bash
while IFS=',' read -r last first
do
    echo "$last $first"
done <test.csv
if [[ $last != "" ]] ; then
    echo "$last $first"
fi

That one works without creating another subshell to modify the input to the whilestatement.

那个不需要创建另一个子shell来修改while语句的输入。



Of course, I'm assuming here that you want to do more inside the loop that just output the values with a space rather than a comma. If that's all you wanted to do, there are other tools better suited than a bashread loop, such as:

当然,我在这里假设您想在循环中执行更多操作,只输出带有空格而不是逗号的值。如果这就是您想要做的,还有其他比bash读取循环更适合的工具,例如:

tr "," " " <test.csv

回答by Andrzej Chabierski

cat file |sed -e '${/^$/!s/$/\n/;}'| while IFS=',' read -r last first; do echo "$last $first"; done

回答by Gordon Davisson

If the last (unterminated) line needs to be processed differently from the rest, @paxdiablo's version with the extra ifstatement is the way to go; but if it's going to be handled like all the others, it's cleaner to process it in the main loop.

如果最后(未终止的)行需要与其他行进行不同的处理,@paxdiablo 的带有额外if语句的版本是可行的方法;但是如果要像所有其他人一样处理它,在主循环中处理它会更干净。

You can roll the "if there was an unterminated last line" into the main loop condition like this:

您可以将“如果有未终止的最后一行”滚动到主循环条件中,如下所示:

while IFS=',' read -r last first || [ -n "$last" ]
do
    echo "$last $first"
done < test.csv