如何基于文件名在文件txt中添加列

时间:2019-12-19 08:50:20

标签: linux bash shell

这是我的剧本

SourceFile='/root/Document/Source/'

FND=$(find $SourceFile. -regextype posix-regex -iregex "^.*/ABCDEF_555_[0-9]{5}\.txt$")
echo $FND
#*I've tried using "awk" but haven't gotten perfect results*

文件名:

ABCDEF_555_12345.txt
ABCDEF_555_54321.txt
ABCDEF_555_11223.txt

之前

File Content from ABCDEF_555_12345.txt:
no|name|address|pos_code
1|rick|ABC|12342
2|rock|ABC|12342
3|Robert|DEF|54321

File Content from ABCDEF_555_54321.txt:
no|id|name|city
1|0101|RIZKI|JKT
2|0102|LALA|SMG
3|0302|ROY|YGY

我想在第二行开始的每一行中追加一个显示文件名的列,并在第一行之后追加具有name_file的列,我想更改原始文件的内容。

之后

file: ABCDEF_555_12345.txt
no|name|address|pos_code|name_file
1|rick|ABC|12342|ABCDEF_555_12345.txt
2|rock|ABC|12342|ABCDEF_555_12345.txt
3|Robert|DEF|54321|ABCDEF_555_12345.txt

file: ABCDEF_555_54321.txt
no|id|name|city|name_file
1|0101|RIZKI|JKT|ABCDEF_555_54321.txt
2|0102|LALA|SMG|ABCDEF_555_54321.txt
3|0302|ROY|YGY|ABCDEF_555_54321.txt

请给我点灯,找到解决方法:)) 谢谢:))

2 个答案:

答案 0 :(得分:2)

最好的解决方案是使用awk。

如果它是第一行(NR == 1),请打印该行并附加|name_file。 对于所有其他行,请打印该行并使用FILENAME变量附加文件名:

awk 'NR == 1 {print $0 "|name_file"; next;}{print $0 "|" FILENAME;}' foo.txt

您可以将其与多个文件一起使用:

find . -iname "*.txt" -print0 | xargs -0 awk '
NR == 1 {print $0 "|name_file"; next;}
FRN == 1 {next;} # Skip header of next files
{print $0 "|" FILENAME;}'

我的第一个解决方案曾经使用paste命令。

粘贴可让您水平连接文件(与cat垂直连接的文件相比)。 要通过paste实现以下目标,请执行以下操作:

  1. 首先将文件的第一行(head -n1 foo.txt)与列标题(echo "name_file")连接起来。命令paste接受-d标志来定义列之间的分隔符。
  2. 第二,提取除第一行(tail -n+2 foo.txt)之外的所有行,并将它们与所需的foo.txt相连(使用for循环,计算要填充的行数。

解决方案如下:

paste -d'|' <(head -n1 foo.txt) <(echo "name_file")
paste -d'|' <(tail -n+2 foo.txt) <(for i in $(seq $(tail -n+2 foo.txt | wc -l)); do echo "foo.txt"; done)
no|name|address|pos_code|name_file
1|rick|ABC|12342|foo.txt
2|rock|ABC|12342|foo.txt
3|Robert|DEF|54321|foo.txt

但是,必须首选awk解决方案,因为它更清晰(只有一个调用,较少的进程替换和合作),而且速度更快。

$ wc -l foo.txt
100004 foo.txt

$ time ./awk.sh >/dev/null
./awk.sh > /dev/null  0,03s user 0,01s system 98% cpu 0,041 total

$ time ./paste.sh >/dev/null
./paste.sh > /dev/null  0,38s user 0,33s system 154% cpu 0,459 total

答案 1 :(得分:0)

使用find和GNU awk

我的find实现没有正则表达式posix-regex,我改用了posix-extended,但是由于得到了正确的结果,所以应该没事。

srcdir='/root/Document/Source/'
find "$srcdir" -regextype posix-regex -iregex ".*/ABCDEF_555_[0-9]{5}\.txt$"\
    -exec awk -i inplace -v fname="{}" '
  BEGIN{ OFS=FS="|"; sub(/.*\//, "", fname) }    # set field separators / extract filename
  { $(NF+1)=NR==1 ? "name_file" : fname; print } # add header field / filename, print line
' {} \;

find找到的路径名在变量awk中传递给fname。在BEGIN块中,从路径中提取文件名。

文件被“就地”修改,请确保在运行此文件之前对文件进行备份。