提取文件以生成并重命名不同的文件

提取文件以生成并重命名不同的文件

我有一个 csv(其中第一列和第二列用“,”分隔)文件,如下所示:

Column1,Column2
4e,info1
4t,info2
45t,info3
3,info4

我想获得 4 个不同的文件,每一行一个,文件名取自 Column1,内容取自 Column2。

我的预期输出是:

文件名1 =4e.smi

info1

文件名2 =4t.smi

info2

文件名3 =45t.smi

info3

文件名4 =3.smi

info4

我认为我可以生成两个不同的变量,一个与第一列相关,另一个与第二列相关,并使用该变量创建新文件,对所有行循环执行此操作。但我尝试了这个命令行,但它不起作用:

while IFS=',' read -r name smile; do write "$smile" "$name".smi; done < InputFIle.txt

有人可以帮我解决这个挑战吗?

谢谢。

答案1

write除了该命令不是您要使用的命令这一事实之外,您的循环几乎是正确的。相反,请printf与重定向一起使用。您还需要确保跳过初始行,我们可以通过多种不同的方式来做到这一点。下面,我使用的是tail -n +2,但您也可以使用sed 1d.

tail -n +2 InputFIle.txt |
while IFS=, read -r name string; do
    printf '%s\n' "$string" >"$name".smi
done

请注意,这假设文件名仅写入一次,就好像两行或多行第一列中具有相同的值一样,后面的行将导致已写入文件的数据被覆盖。因此,您可能想要更改>>>附加到输出文件。如果您想运行代码两次(否则您将在输出中获得重复的数据),则此更改将要求您额外删除这些文件。

awk一种可能更有效的方法是像这样使用:

awk -F, 'NR > 1 { print $2 >($1 ".smi") }' InputFIle.txt

这会将第二个逗号分隔字段打印到第一个字段给出的文件名。它通过NR针对 1 进行测试(到目前为止读取的记录数)来跳过第一行。

这不会遇到与 shell 循环相同的问题。输出文件将在第一个文件后被截断(清空或创建)print,然后附加后续输出。

如果某些行上有更多字段,awk则需要修改变体以打印除第一个字段之外的所有字段:

awk -F, 'NR > 1 { name = $1; sub("[^,]*,",""); print >(name ".smi") }' InputFIle.txt

这会将第一个字段保存在单独的变量 中,name然后使用 从原始行中删除该字段sub()。然后它将剩余的行打印到文件中。

答案2

无论需要生成多少个输出文件,使用任何 tail+sort+awk 都可以有效地工作:

tail -n +2 file | sort | awk -F, '$1!=prev{close(out); out=$1".smi"; prev=$1} {print $2 > out}'

如果您没有随时关闭输出文件,那么大多数 awk 可能会遇到“打开文件过多”错误,或者 GNU awk 会显着减慢速度,因为它会尝试为您管理打开/关闭文件,一旦超过了我见过的低于 20 个输出文件的阈值。我们首先进行排序,这样我们就不必每次在输入中看到重复的 $1 时都打开/关闭输出文件。

相关内容