我有一个主列表master.csv
,看起来像:
line1
line2
bill, 1
sonia, 2
rhonda, 3
patty, 4
和我要过滤的名单文件:
bill
rhonda
我想保留master.txt
的标头,所以我做head -n 2 master.csv >out.csv && grep -f roster.txt master.txt >>out.csv
并得到:
line1
line2
bill, 1
rhonda, 3
这很棒,但是我必须一直这样做,所以我将其包装在一个函数中:
filterSections(){
head -n 2 /dev/stdin && grep -f $1 /dev/stdin
}
因此,从理论上讲,我可以做filterSections roster.txt <master.csv >out.csv
,
但我只会得到:
line1
line2
在我的大文件上,似乎只缺少第一行。谢谢
答案 0 :(得分:2)
您的函数应该可以使用,但是您应该避免在stdin上放置大量数据。您可以使用以下单个awk
命令来获得相同的输出:
awk -F, 'FNR==NR{seen[$1]; next} FNR <= 2 || $1 in seen' roster.txt master.csv
line1
line2
bill, 1
rhonda, 3
要将其放在函数中:
filterSections() {
awk -F, 'FNR == NR { seen[$1]; next } FNR <= 2 || $1 in seen' "$1" "$2"
}
称呼为:
filterSections roster.txt master.csv
不好意思的解释:
-F,
:以逗号作为输入定界符FNR == NR
:对于输入中的第一个文件,即roster.txt
{ seen[$1]; next }
:将$1
(第一列)存储在关联数组seen
中,并移至同一文件中的下一条记录FNR <= 2
:第二文件的记录号为<= 2
||
:或$1 in seen
:在关联数组seen
中找到第二个文件的第一列参考:
答案 1 :(得分:2)
问题在于Verify
正在读取大量数据,然后仅写入2行。到head
尝试从文件描述符读取时,已经没有数据了。这是一个众所周知的问题,内置的grep
外壳用于处理此问题:
read
请注意,默认情况下,filterSections(){
read line # Read all characters up to first newline, and no more
echo "$line"
read line # Read the 2nd line, and no more
echo "$line"
grep -f "$1"
}
和read
是从stdin读取的,因此无需指定grep