使用bash/sed将文件名的一部分前置到.csv文件

使用bash/sed将文件名的一部分前置到.csv文件,bash,csv,sed,Bash,Csv,Sed,我在一个目录中有几个文件,它们的名称如下 1_38OE983729JKHKJV.csv 后跟ID的整数(整数和ID都是唯一的) 我需要为文件夹中的每个文件的每一行预先添加此ID,以准备导入数据库的文件(并放弃文件名的整数部分)。文件内容如下所示: BW;20015;11,45;0,49;41;174856;4103399 BA;25340;11,41;0,55;40;222161;4599779 BB;800;7,58;0,33;42;10559;239887 HE;6301;9,11;0,3

我在一个目录中有几个文件,它们的名称如下

1_38OE983729JKHKJV.csv
后跟ID的整数(整数和ID都是唯一的)

我需要为文件夹中的每个文件的每一行预先添加此ID,以准备导入数据库的文件(并放弃文件名的整数部分)。文件内容如下所示:

BW;20015;11,45;0,49;41;174856;4103399
BA;25340;11,41;0,55;40;222161;4599779
BB;800;7,58;0,33;42;10559;239887
HE;6301;9,11;0,39;40;69191;1614302
.
.
.
Total;112613;9,33;0,43;40;1207387;25897426
38OE983729JKHKJV;BW;20015;11,45;0,49;41;174856;4103399
38OE983729JKHKJV;BA;25340;11,41;0,55;40;222161;4599779
38OE983729JKHKJV;BB;800;7,58;0,33;42;10559;239887
38OE983729JKHKJV;HE;6301;9,11;0,39;40;69191;1614302
.
.
.
38OE983729JKHKJV;Total;112613;9,33;0,43;40;1207387;25897426
最终结果应该如下所示:

BW;20015;11,45;0,49;41;174856;4103399
BA;25340;11,41;0,55;40;222161;4599779
BB;800;7,58;0,33;42;10559;239887
HE;6301;9,11;0,39;40;69191;1614302
.
.
.
Total;112613;9,33;0,43;40;1207387;25897426
38OE983729JKHKJV;BW;20015;11,45;0,49;41;174856;4103399
38OE983729JKHKJV;BA;25340;11,41;0,55;40;222161;4599779
38OE983729JKHKJV;BB;800;7,58;0,33;42;10559;239887
38OE983729JKHKJV;HE;6301;9,11;0,39;40;69191;1614302
.
.
.
38OE983729JKHKJV;Total;112613;9,33;0,43;40;1207387;25897426
谢谢你的帮助


编辑:拼写和发音为清晰起见

使用在文件上循环,使用参数展开提取id

#!/bin/bash
for csv in *.csv ; do
    prefix=${csv%_*}
    id=${csv#*_}
    id=${id%.csv}
    sed -i~ "s/^/$id;/" "$csv"
done
如果ID可以包含下划线,则可能需要更加小心地进行扩展。

使用awk工具:

for f in *csv; do awk '{ fn=FILENAME; $0=substr(fn,index(fn,"_")+1,length(fn)-6)";"$0 }1' "$f" > tmp && mv tmp "$f"; done
  • fn=FILENAME
    -文件名

在单个awk中也尝试以下操作,这也将考虑在此操作期间打开的文件数,因此我们将避免最大打开文件数的错误

awk 'FNR==1{close(val);val=FILENAME;split(FILENAME,a,"_");sub(/\..*/,"",a[2])} {print a[2]","$0}' *.csv

使用GNU awk进行就地编辑和gensub()只需:

awk -i inplace '{print gensub(/.*_(.*)\..*/,"\\1;",1,FILENAME) $0}' *.csv

没有shell循环或任何其他必要的东西,只有该命令。

它给我这个错误:我的输入:sh addId.sh:command not found'ddId.sh:第3行:意外标记附近的语法错误
do'ddId.sh:line 3:
for csv in*.csv;doDon不要用
sh
调用
bash
脚本。我的错,谢谢!我习惯于使用macOS,sh实际上调用bash而不是标准的BourneShell。活到老学到老!我必须如何执行此操作?这必须在同一个目录中吗?@Tassanara:尝试在终端上运行,它只会打印行,如果您需要输出到单个输出文件,那么您可以在命令的最后执行>输出文件,然后告诉我它是如何运行的。@Tassanara:很高兴它帮助了您。这对多个文件不起作用。例如,
close(val)
正试图关闭以前的
FILENAME
值,但
close()
仅适用于由于重定向而打开的文件(例如,
print>file
getline
),而不是作为常规工作循环的一部分。显然,打印到stdout一次只能处理1个文件,但不要尝试
*.csv
。如果要对文件名使用split(),为什么不同时在
\uu
处拆分它,而不是在
\u
处拆分它,然后在
处拆分子()呢?split()的第三个参数是regexp,顺便说一句,不是字符串。最后,所需的分隔符是
,而不是
;。