我是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
如果有人对如何改进我的脚本或任何新想法(再次使用循环)有任何想法,将不胜感激。谢谢!
答案 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