在 bash 上逐行读取文件;每一行都包含另一个 unqiue 文件的路径

Posted

技术标签:

【中文标题】在 bash 上逐行读取文件;每一行都包含另一个 unqiue 文件的路径【英文标题】:Read a file line-by-line on bash; each line containing the path to another unqiue file 【发布时间】:2019-06-12 04:18:58 【问题描述】:

给定文件“a.txt”中的每一行都包含另一个唯一文件的目录/路径。假设我们要逐行解析'a.txt',提取字符串格式的路径,然后使用vim等工具处理该路径下的文件,以此类推。

通过这个线程 - Read a file line by line assigning the value to a variable 之后,我编写了以下脚本,在 bash 上说 'open-file.sh'(我是新手)

#!/bin/bash
while IFS='' read -r line || [[ -n "$line" ]]; do
  vim -c ":q" -cq $line # Just open the file and close it using :q 
done < "$1"

然后我们将上面的脚本运行为 -

./open-file.sh a.txt

问题是虽然$line正确指定了新文件的路径,但是当vim打开文件时,vim继续接收'a.txt'中包含的文本作为命令.如何编写一个脚本,我可以正确地从 'a.txt' 获取路径,使用 vim 打开它,然后继续解析 'a.txt中的剩余行>' ?

【问题讨论】:

【参考方案1】:

替换:

vim -c ":q" -cq $line

与:

vim -c ":q" -cq "$line" </dev/tty

重定向&lt;/dev/tty 告诉vim 从终端获取其标准输入。没有它,vim 的标准输入是"$1"

此外,最好将$line 放在双引号中,以防止分词等。

最后,虽然vim 非常适合交互式工作,但如果您的最终目标是全自动处理每个文件,您可能需要考虑使用sedawk 等工具。

【讨论】:

将检查您提到的其他工具。【参考方案2】:

虽然我不确定你的最终目标,但这个 shell 命令将在a.txt 中每行执行一次 vim:

xargs -o -n1 vim -c ':q' &lt; a.txt

正如Read a file line by line assigning the value to a variable 的 cmets 中所解释的,您遇到的问题是由于 vim 是一个交互式程序,因此会继续读取来自 $line 的输入。

【讨论】:

xargs -o 在我的GNU findutils 4.7.0 中不可用。从man xargs 看来,-o 是特定于 BSD 的。 引用: xargs sh -c 'emacs "$@" &lt; /dev/tty' emacs [...] 这个例子实现了与 BSD 的 -o 选项相同的效果,但以更灵活和可移植的方式。 有趣且值得留意。我还在 Ubuntu 上使用 GNU findutils 4.7.0,并且手册页指出添加了 -o 是为了更好地与 BSD 兼容。 这很奇怪。完整版是xargs (GNU findutils) 4.7.0-gitCopyright (C) 2016 [...]。我在 Linux (WSL) 的 Windows 子系统中使用 Ubuntu 16.04.3 LTS。当我尝试执行命令时,我得到xargs: invalid option -- 'o'. 我使用的是 Ubuntu 18.04,所以我猜他们是最近才添加的。【参考方案3】:

问题是already mentioned in a comment 在您基于脚本的答案下。

vim 正在消耗由done &lt; $1 提供给循环的stdin。我们可以在以下示例中观察到相同的行为:

$ while read i; do cat; done < <(seq 3)
2
3

&lt;(seq 3) 模拟具有123 三行的文件。而不是三个静默迭代,我们只得到一个迭代和输出23

stdin 不仅传递给循环头部的read,还传递给循环体的cat。因此read 读取一行,进入循环,cat 读取所有剩余行,stdin 为空,read 没有内容可读取,循环退出。

您可以通过将某些内容重定向到vim 来规避该问题,但是还有更好的方法。你根本不需要循环:

< "$1" xargs -d\\n -n1 vim -c :q -cq

xargs 将对$1 给出的文件中的每一行执行一次vim

【讨论】:

啊,是的,答案在评论中。

以上是关于在 bash 上逐行读取文件;每一行都包含另一个 unqiue 文件的路径的主要内容,如果未能解决你的问题,请参考以下文章

C++ 逐行读取文件,然后使用分隔符分割每一行

逐行读取文件数据,分析每一行数据与目标字符串的相似度,Python

如何在 Java 中逐行读取文本文件并分隔每一行的内容?

在 C# 中逐行读取文件

如何逐行读取文本文件并使用android将每一行存储在数组中?可以在android中读取xls文件吗?

使用for循环bash脚本逐行读取文件[重复]