这是我的剧本
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
请给我点灯,找到解决方法:)) 谢谢:))
答案 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
实现以下目标,请执行以下操作:
head -n1 foo.txt
)与列标题(echo "name_file"
)连接起来。命令paste
接受-d
标志来定义列之间的分隔符。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
块中,从路径中提取文件名。
文件被“就地”修改,请确保在运行此文件之前对文件进行备份。