提问人:Richard T 提问时间:8/6/2023 最后编辑:Mark RotteveelRichard T 更新时间:8/12/2023 访问量:82
如何避免从文件中读取行的 subshell 问题?[复制]
How to avoid subshell issues with reading lines from a file? [duplicate]
问:
这篇文章是 4 个月前编辑并提交审核的,未能重新打开帖子:
需要更多关注通过编辑这篇文章来更新问题,使其仅关注一个问题。
“回到过去”,1990 年代中期,我不得不编写一个名为 “” 的 C 程序,以避免在进行类似构造时因子壳而产生的全局变量与局部变量问题:readline
while read line
do
my_var=$(echo "$line" | cut -f 12 -d ":")
if [ "$my_var" == "$target" ] ;
then
found_target=1
fi
done < some_file
在更新这个问题以希望能解决一些评论时,我意识到另一个我对这种类型的循环一无所知的问题;你如何实现“我们已经找到了目标,我们现在可以停止阅读了!使用这种类型的循环?我猜这应该涉及:
while [ -z "$found_target" ] &&
但是我不知道如何完成这条线!为了“正常工作”,该示例必须在循环中保留found_target和my_var,以便循环后面的代码使用。
请注意,这里的代码示例不是我今天使用的代码示例,原因很简单,输入重定向(<文件构造)到 while 循环造成的“被烧毁”问题,我不再这样做了!在下面的“背景故事”中,你可能会看到这个想法是如何开始的,但它可能都是基于对 Bash 的误解。
简而言之,观察到在读取处理期间在循环中设置的变量(例如本例中的found_target)在循环退出时丢失。一个应该是 Bash 专家的人(早在 1995 年到 97 年)告诉我们——我领导的团队——这是因为循环的内部被放入了一个子壳中。我是一个数据库人,做过机器语言编码,等等,等等,甚至不认为 Bash 是一种编程语言。因此,鉴于交给我的问题需要解决,我只是将一个阅读线程序交还给团队,使他们能够克服困难。
我的简单程序只有一个或两个参数;你告诉它你想要的整数行号,然后通过传递文件或通过文件规范将其指向文件。由于操作系统缓存,它并不像人们想象的那么低效。而且,它让这些技能更差的程序员继续他们的工作。stdin
这个程序非常令人满意,特别是对于大文件——文件越大,胜利就越大,因为 Bash 在这种使用中不是(或至少不是)特别有效,更不用说子壳/全局变量问题了。(请注意以下部分,了解为什么这有意义!
然而,现在我想重新审视这个问题,原因有两个:1)Bash 及其附带的实用程序在过去二十多年中已经/已经取得了长足的进步,并且;2)我想在不依赖我的程序的情况下为某人提供一些软件,对于这个问题,subshell问题是真正的问题 - 并且将使用它的人,就像我为之编写readline的原始人一样,而不是真正的程序员。但是,如果有我的开源版本,那就可以了!readline
readline
除了这些动机之外,虽然从那时起我在理解 Bash 方面取得了长足的进步,但对我来说,它仍然是一个主要的第三级问题,我知道我仍然对它的大部分内容一无所知。我认为“正确的方法”可能是更智能地使用功能。那时,我对重定向到 BASH 函数和从 BASH 函数重定向的能力一无所知。而且,坦率地说,虽然现在我知道“这是一个东西”,但我从未真正使用过它。
一些背景故事
对于“逆向计算”社区来说,这绝对是这样的事情:早在 1995 年或 1996 年,当这个“不要那样做!”的想法出现时,Bash 被用作“胶水层”的一部分,试图连接大约 7 个系统,这些系统由不同的团队为地球科学的不同方面设计。这些系统都不是设计得那么好,都是由地球科学家完成的,他们热衷于地球,而不是计算机。对于大多数人来说,他们对数据库的想法是粗糙的,通常是大文件中的大文本行,他们想要的只是在当时被认为是巨大的文件中间挑选几行可能相邻的行。而且,要把大气数据与海面数据结合起来,最好的办法是让一些研究生或博士后编写 Bash 代码,将其他代码的一点点组合在一起。
值得一提的是,我的目标是让他们使用关系数据库引擎,事实上,现代PostgreSQL同时来自同一个实验室。然而,我管理的最好的办法是使用数据库作为元层,知道哪些数据在哪些系统中,如何访问这些系统,以及调用哪些程序来实际执行数据连接的科学部分。希望这个题外话能给它一些视角来解释为什么!
嘿,如果整个子壳问题完全是错误的,请教我!我可以被教导!否则,关于替换我的读行的建议会很好。
答: 暂无答案
评论
x="$line"
echo "$x"
awk 'NR==123' file.txt
head -n 123 file.txt | tail -n 1
sed -n '123p' file.txt'
readline
while read ... done < some_file
somecommand | while read ...
while read
read
read
sed
awk