在 bash 中,我必须询问第一个 csv 文件、第二个 csv 文件中的每一行以及第三个 csv 文件中的答案...
第一个文件。例如aaa.csv
:
aaa
bbb
aaa
aaa
ccc
fff
aaa
第二个文件,例如bbb.csv
:
aaa;111
bbb;222
ccc;333
ddd;444
eee;555
ggg;666
第三个文件,例如ccc.csv
:
aaa;111
bbb;222
aaa;111
aaa;111
ccc;333
fff;
aaa;111
这可能吗?在这个空白处可能是错误的词或其他东西。当我使用 then 时,只有当 111 出现 aaa 时,才cat bbb.csv | grep -f aaa.csv > ccc.csv
用部分常见的 the 来回答。aaa.csv
答案1
注释中的另一种可能的方法可以使用awk
更改的文件顺序:
awk -F';' 'FNR == NR { m[$1] = $2; next; } { if ($1 in m) { print $1 ";" m[$1]; } else { print $1 ";FALSE"; } }' bbb aaa
首先,我们读取文件 bbb 将值存储在数组中,其中包含第一列的键值,然后读取文件 aaa 并检查数组中是否存在键并相应地打印。
结果:
aaa;111
bbb;222
aaa;111
aaa;111
ccc;333
fff;FALSE
aaa;111
答案2
你可以这样做:
while read linea
do
grep "$linea" bbb.csv >> ccc.csv || echo "$linea:FALSE" >> ccc.csv
done < aaa.csv
$ cat ccc.csv
aaa;111
bbb;222
aaa;111
aaa;111
ccc;333
fff:FALSE
aaa;111
答案3
一些元 sed 怎么样:
sed "$(sed 's^\(.*\);\(.*\)^s/\1/\1;\2/;tx^;$as/.*/&;FALSE/\n:x' bbb.csv)" aaa.csv
内部 sed 表达式转换bbb.csv
为如下 sed 程序:
s/aaa/aaa;111/;tx
s/bbb/bbb;222/;tx
s/ccc/ccc;333/;tx
s/ddd/ddd;444/;tx
s/eee/eee;555/;tx
s/ggg/ggg;666/;tx
s/.*/&;FALSE/
:x
然后由外部 sed 解释以转换aaa.csv
为所需的输出:
aaa;111
bbb;222
aaa;111
aaa;111
ccc;333
fff;FALSE
aaa;111
请注意tx
生成的 sed 程序中的 。x:
如果前面的s
替换匹配,这些是 sed 条件跳转到标签。这允许最后插入一个包罗万象的语句来替换“FALSE”文本。
这个答案需要注意的是它不会扩展到大bbb.csv
文件,因为生成的整个程序都是在命令行上传递的。如果这是一个问题,可以将生成的程序放入临时文件中:
sed 's^\(.*\);\(.*\)^s/\1/\1;\2/;tx^;$as/.*/&;FALSE/\n:x' bbb.csv > bbb.tmp.sed
sed -f bbb.tmp.sed aaa.csv > ccc.csv
如果最终非常大,这仍然会受到限制bbb.tmp.sed
- 我认为 sed 会尝试将整个文件读入内存。
答案4
我强烈建议使用 Python 而不是任何 shell 工具来编写这个特定的脚本,因为 Python 的标准库包含一个 CSV 解析器,它实际上可以处理 CSV 语法中的所有古怪问题。你会做这样的事情:
import csv
import sys
# sys.argv[1] = "aaa.csv", sys.argv[2] = "bbb.csv"
# sys.argv[3] = default value for mapping
# output written to stdout
with open(sys.argv[2], "rt") as f:
rd = csv.reader(f, dialect="unix", delimiter=";")
mapping = { row[0] : row[1] for row in rd }
with open(sys.argv[1], "rt") as f:
rd = csv.reader(f, dialect="unix", delimiter=";")
wr = csv.writer(sys.stdout, dialect="unix", delimiter=";",
quoting=csv.QUOTE_MINIMAL)
for row in rd:
wr.writerow([row[0], mapping.get(row[0], sys.argv[3])])
然后运行它,例如python munge.py aaa.csv bbb.csv "" > ccc.csv
。
一般来说,如果不清楚如何在 shell 脚本中执行某些操作,请考虑不在 shell 脚本中执行此操作。除非对任意硬性安装的可移植性比还要别的吗(例如,在 Autoconf 宏的内部)您会更乐意编写 Perl、Python、Ruby、node.js 等。