我有一个主列表,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
在我的较大文件中,它似乎只缺少第一行。谢谢
你的函数应该可以工作,但你应该避免在标准上放置大量数据。您可以使用此单个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
awk解释:
-F,
:将逗号作为输入分隔符FNR == NR
:对于输入中的第一个文件,即roster.txt
{ seen[$1]; next }
:将$1
(第一列(存储在关联数组seen
中,并移动到同一文件中的下一条记录FNR <= 2
:当第二个文件的记录编号<= 2
||
: 或$1 in seen
:在关联数组中找到第二个文件中的第一列seen
引用:
- 有效的 AWK 编程
- awk 教程
问题是head
正在读取大量数据,然后只写入 2 行。 当grep
尝试从文件描述符中读取时,已经没有数据了。 这是一个众所周知的问题,shell 内置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
和grep
从 stdin 读取,因此无需指定/dev/stdin