使用 shell 脚本将文本文件转换为 csv
Convert text file to csv using shell script
我有一个这样的文件
InputFile.txt
JOB JOB_A
Source C://files/InputFile
Resource 0 AC
User Guest
ExitCode 0 Success
EndJob
JOB JOB_B
Source C://files/
Resource 1 AD
User Current
ExitCode 1 Fail
EndJob
JOB JOB_C
Source C://files/Input/
Resource 3 AE
User Guest2
ExitCode 0 Success
EndJob
我必须将上述文件转换为 csv 文件,如下所示
如何使用 shell 脚本转换它?
我用过awk。
分隔符是制表符,因为它比 CSV 格式中的逗号更常见。
如果你想要昏迷,你可以简单地改变 \t
-> ,
.
cat InputFile.txt | \
awk '
BEGIN{print "Source\tResource\tUser\tExitCode"}
/^JOB/{i=0}
/^\s/{
i++;
match([=10=],/\s*[a-zA-Z]* /);
a[i]=substr([=10=],RLENGTH+RPOS)}
/^EndJob/{for(i=1;i<5;i++) printf "%s\t",a[i];print ""}'
- 第一行
BEGIN
写header.
- 第二行匹配
/JOB/
,只设置一个迭代器i
为零。
- 第三行匹配行首的空白并用值填充数组
a
(它严格计算行数和顺序)。
- awk 脚本的第四部分匹配
EndJob
并打印存储的值。
输出:
Source
Resource
User
ExitCode
C://files/InputFile
0 AC
Guest
0 Success
C://files/
1 AD
Current
1 Fail
C://files/Input/
3 AE
Guest2
0 Success
使用关联数组的脚本:
您可以更改脚本,以便使用 $1(第一条记录)行中的严格源、资源、用户和 ExitCode 值,但它会稍长一些,并且此输入文件不需要它。
cat InputFile.txt | \
awk '
BEGIN{
h[1]="Source";
h[2]="Resource";
h[3]="User";
h[4]="ExitCode";
for(i=1;i<5;i++) printf "%s\t",h[i];print ""}
/^\s/{
i++;
match([=11=],/\s*[a-zA-Z]* /);
a[]=substr([=11=],RLENGTH+RPOS)}
/^EndJob/{for(i=1;i<5;i++) printf "%s\t",a[h[i]];print ""}'
with sed ...不知道 InputFile.txt 中的顺序是否始终相同
作为源、资源、用户、退出代码,但如果它是
declare delimiter=";"
sed -Ez "s/[^\n]*(Source|Resource|User) ([^\n]*)\n/${delimiter}/g;s/[ \t]*ExitCode //g;s/[^\n]*JOB[^\n]*\n//gi;s/^/Source${delimiter}Resource${delimiter}User${delimiter}ExitCode\n/" < InputFile.txt > output.csv
我有一个这样的文件
InputFile.txt
JOB JOB_A
Source C://files/InputFile
Resource 0 AC
User Guest
ExitCode 0 Success
EndJob
JOB JOB_B
Source C://files/
Resource 1 AD
User Current
ExitCode 1 Fail
EndJob
JOB JOB_C
Source C://files/Input/
Resource 3 AE
User Guest2
ExitCode 0 Success
EndJob
我必须将上述文件转换为 csv 文件,如下所示
如何使用 shell 脚本转换它?
我用过awk。
分隔符是制表符,因为它比 CSV 格式中的逗号更常见。
如果你想要昏迷,你可以简单地改变 \t
-> ,
.
cat InputFile.txt | \
awk '
BEGIN{print "Source\tResource\tUser\tExitCode"}
/^JOB/{i=0}
/^\s/{
i++;
match([=10=],/\s*[a-zA-Z]* /);
a[i]=substr([=10=],RLENGTH+RPOS)}
/^EndJob/{for(i=1;i<5;i++) printf "%s\t",a[i];print ""}'
- 第一行
BEGIN
写header. - 第二行匹配
/JOB/
,只设置一个迭代器i
为零。 - 第三行匹配行首的空白并用值填充数组
a
(它严格计算行数和顺序)。 - awk 脚本的第四部分匹配
EndJob
并打印存储的值。
输出:
Source | Resource | User | ExitCode |
---|---|---|---|
C://files/InputFile | 0 AC | Guest | 0 Success |
C://files/ | 1 AD | Current | 1 Fail |
C://files/Input/ | 3 AE | Guest2 | 0 Success |
使用关联数组的脚本:
您可以更改脚本,以便使用 $1(第一条记录)行中的严格源、资源、用户和 ExitCode 值,但它会稍长一些,并且此输入文件不需要它。
cat InputFile.txt | \
awk '
BEGIN{
h[1]="Source";
h[2]="Resource";
h[3]="User";
h[4]="ExitCode";
for(i=1;i<5;i++) printf "%s\t",h[i];print ""}
/^\s/{
i++;
match([=11=],/\s*[a-zA-Z]* /);
a[]=substr([=11=],RLENGTH+RPOS)}
/^EndJob/{for(i=1;i<5;i++) printf "%s\t",a[h[i]];print ""}'
with sed ...不知道 InputFile.txt 中的顺序是否始终相同 作为源、资源、用户、退出代码,但如果它是
declare delimiter=";"
sed -Ez "s/[^\n]*(Source|Resource|User) ([^\n]*)\n/${delimiter}/g;s/[ \t]*ExitCode //g;s/[^\n]*JOB[^\n]*\n//gi;s/^/Source${delimiter}Resource${delimiter}User${delimiter}ExitCode\n/" < InputFile.txt > output.csv