任务:使用 bash,迭代一个文件(例如,file1.txt),一次 2 行,提示是否应将每个找到的对联复制到第二个文件(例如,file2.txt)。该命令grep -A 1 "searchterm" file1.txt
给出了我正在寻找的输出类型。因此,脚本应该迭代每几行,询问是否将对联复制到第二个文件,然后递增并对接下来的几行执行相同的操作,依此类推,直到文件末尾。该文件总共大约包含 4000 行,我想将其中的 400 行左右复制到第二个文件中。
文件的内容类似于以下示例:
#searchterm blah
possible additional needed line 1
#searchterm blee
possible additional needed line 2
#searchterm blob
possible additional needed line 3
#searchterm bloh
possible additional needed line 4
#searchterm bluh
possible additional needed line etc
复制到第二个文件cp >>
显然可以通过将其添加到文件末尾来完成。我认为 for 循环和/或 while 可能适用于此。它的增量部分目前有点逃避我。但我的 bash 脚本技能/知识充其量只是中等。意见将不胜感激。
稍后编辑 这是做我所追求的事情的开始(无耻地从https://stackoverflow.com/questions/8314499/read-n-lines-at-a-time-using-bash):
while read -r ONE; do
read -r TWO
echo $ONE
echo $TWO
sleep 3
# replace above sleep command with command(s) that copy lines or exit back to while loop
done < file1.txt
这一次读取 file1.txt 两行,将每个对联输出到终端。 sleep 3 行需要替换为一些例程,该例程将询问用户输入,例如“您想将这两行复制到 file2.txt 吗?回答 y 或 n。”如果用户选择 y,则printf $ONE >>file2.txt && printf $TWO >>file2.txt
在返回while
接下来两行的循环之前会运行类似的操作。如果用户回答 n,则循环将返回到上次停止的位置,将 file1.txt 的接下来两行输出到终端并询问相同的问题。进步?
后来的编辑:第一次尝试完整的解决方案失败
while read -r ONE; do
read -r TWO
echo $ONE
echo $TWO
read -n 1 -p "Would you like to copy the above 2 lines to the new file? [Y,n]" ans
if [[ $ans == "Y" || $ans == "y" ]]; then
printf $ONE >>file2.txt && printf $TWO >>file2.txt
else
echo "Resuming loop"
fi
done < file1.txt
不起作用,这意味着它的输出与cat file1.txt
从命令行运行没有太大不同。但也许它能让我更好地了解我希望通过脚本实现什么目标。
后来编辑:半运行 进一步的研究表明,也许我需要一种称为文件描述符的东西来完成这项工作。使用此链接https://stackoverflow.com/questions/8886683/read-stdin-for-user-input-when-a-file-is-already-redirected-to-stdin我将脚本修改如下
while read -r ONE <&3; do
read -r TWO <&3
echo $ONE
echo $TWO
read -n 1 -p "Would you like to copy the above 2 lines to the new file? [Y,n]" ans
if [[ $ans == "Y" || $ans == "y" ]]; then
printf $ONE >>file2.txt && printf $TWO >>file2.txt
else
echo "Resuming loop"
fi
done 3<file1.txt
这实际上允许我将正在读取的文件中的行对复制到标准输入到另一个文件。差不多是我想要的。我只需要弄清楚如何在正在创建的文件中引入换行符,以便将行对复制到不会最终位于同一行上。欢迎进一步的输入和解释。
答案1
只需更改该行:
printf $ONE >>file2.txt && printf $TWO >>file2.txt
到
printf "$ONE\n" >>file2.txt && printf "$TWO\n" >>file2.txt
这应该将每个 printf 语句的输出放在新行上。
答案2
使用乐(以前称为 Perl_6)
raku -ne 'm/blah | blob/ ?? put($_, "\n", get) !! next;'
#OR
raku -e 'for lines() { m/blah | blob/ ?? put($_, "\n", get) !! next};'
或者
raku -e 'for lines.rotor(2) { .join("\n").put if m/blah | blob/ };'
#OR
raku -e 'for lines.batch(2) { .join("\n").put if m/blah | blob/ };'
一定是这样吗bash
?这是用 Raku 写的答案。 Raku 的lines
例程延迟读取输入,因此它应该非常高效。前两个答案返回匹配行,然后get
s-and- 返回每个匹配后面的行。
第三个答案rotor
将每个对句放在一起,以便一次分析两行。由于rotor
在最后删除了“不完整/部分”分组,因此第四个示例使用batch
返回部分分组(与 相同rotor(2, partial => True)
)。
输入示例:
#searchterm blah
possible additional needed line 1
#searchterm blee
possible additional needed line 2
#searchterm blob
possible additional needed line 3
#searchterm bloh
possible additional needed line 4
#searchterm bluh
possible additional needed line etc
示例输出(所有四个示例):
#searchterm blah
possible additional needed line 1
#searchterm blob
possible additional needed line 3