使用循环

时间:2017-09-18 14:53:02

标签: bash shell loops command-line

我是shell脚本的新手,我在执行以下任务时遇到了一些麻烦: 我想从file2中提取也在file1中找到的行,并将这些行提取到新文件3。我只允许使用循环(我知道它适用于基本的grep命令,但我需要找到一个带循环的方法)

File1中

John 5 red books
Ashley 4 yellow music
Susan 8 green films

文件2

John
Susan

file3的所需输出为:

John 5 red books
Susan 8 green films

必须使用bash脚本和循环找到所需的输出。我尝试了以下循环,但是我在结果中缺少一些使用它的行:

while read line
do
grep "${line}" $file1
done < $file2 >> file3.txt

如果有人对如何改进我的脚本或任何新想法(再次使用循环)有任何想法,将不胜感激。谢谢!

4 个答案:

答案 0 :(得分:1)

由于您正在使用Bash,您可以从File2创建一个关联数组,并使用它来检查成员资格。像(未经测试)的东西:

read -a names <File2
local -A n
for i in "${names[@])"
do n["$i"]="$i"
done

while read name rest
do [ "${n[$name]}" ] && echo "$name $rest"
done <File1 >file3

答案 1 :(得分:1)

在这里循环是一项很好的教育练习,但在现实世界中它并不是理想的。

从技术上讲,这个awk解决方案可以工作并使用一个循环,但我猜测它并不是你的教练正在寻找的东西:

awk 'NR == FNR { seen[$1]=1; next } seen[$1]' File1 File2

这循环遍历第一个文件(NR是所有输入中到目前为止所见的&#34;记录数和#34;(行),FNR是当前文件&#39; s记录数,因为第一个子句要求它们是相同的值,它只能触发第一个输入文件。它设置一个哈希(一个带有键/值对的数据结构,也就是一个关联数组或字典),其键是行上第一列($1)的值,因此我们可以稍后提取它,然后跳过该输入行的后一节。

当代码循环遍历第二个文件时,第一个子句不会触发,而是在seen哈希中查找第一列输入。如果它存在,则其值为1并且计算结果为true,因此我们打印该值。 (没有动作的条款意味着{ print }

哈希绝对是最优化的计算方法;相比之下,其他任何东西都非常昂贵。这是一个使用与散列相同的基本概念但在技术上不散列的解决方案。它包含隐式循环仅仅是由于排序和文件读取的工作方式。 (为了防止包装,我已经积极地崩溃了空白。如果print$1代替print $1,AWK不会抱怨,因为${awk '{print$1}' File1 |sort -u; awk '{print$1}' File2 |sort -u;} |sort |uniq -d 已经暗示领先空间的特殊字符。)

sort File1 File2

这会分别对File1和File2进行独特排序,以删除每个文件中的重复条目(如果您知道他们没有任何重复条目,您可以uniq -d)然后对整个文件进行排序以便{ {1}}只能显示重复的行。

请参阅Toby Speight's answer了解仅使用内置的本机bash答案。它使用循环和哈希。

答案 2 :(得分:0)

Awk解决方案:

awk 'NR==FNR{ arr[$0]="";next } { for (i in arr) { if (i == $1 ) { print $0 } } }' file2 file1

首先,我们使用file2中的数据创建一个数组。然后,我们使用它来检查第一个以空格分隔的数据,如果匹配则打印,

答案 3 :(得分:0)

使用awk:

$ awk 'NR==FNR{ a[$1];next } $1 in a' file2 file1`

使用grep:

$ grep -F -f file2 file1