用于从文本文件中提取数据的 Shell 脚本
Posted
技术标签:
【中文标题】用于从文本文件中提取数据的 Shell 脚本【英文标题】:Shell script to extract data from text file 【发布时间】:2015-12-04 20:32:35 【问题描述】:我制作了一个 shell 脚本,它应该提取具有某些字段名称的数据并将它们放入 CSV 文件中。
一个示例输入文件可能有以下几行:
user_name: null@gmail.com
EMAIL: null@gmail.com
FIRST_NAME: jonathan
LAST_NAME: doestein
CREATION_DATE: 2013-08-01 01:08:52
REGISTRATION_STATUS: Y
VENDOR: vendorname
这会重复“n”次。
这是我目前编写的脚本的摘录:
#!/bin/sh
echo "Please enter input file name."
read input_variable
echo "You entered: $input_variable"
echo "Please enter a name of the new output file."
read output_file
touch $output_file
echo "The output file name is going to be $output_file"
echo "Extracting files..." ;
awk '$1 ~ /^(user_name:|EMAIL:|FIRST_NAME:|LAST_NAME:|CREATION_DATE:|REGISTRATION_STATUS:)$/printf "%s,",$2 $1 ~ /REGISTRATION_STATUS:/print $2' $input_variable >> $output_file.ib ;
但是,尽管数据会打印到我的输出文件(必须是 .csv 扩展名才能让 GUI 查看),但当我在 OpenOffice Calc 等 GUI 中打开文件时,同一行中连接了许多行,而其他行似乎像他们应该的那样开始一个新行。
例如,一行可能如下所示:
noway@gmail.com,noreally51,noway,username,username...x40 or so
usnername,username,username.... 这意味着它只在一行中列出了大约 40-50 个用户名,然后最后转到下一行并打印信息。
我想在输出文件中添加列名:
VENDOR,user_name,FIRST_NAME,LAST_NAME,CREATION_DATE,REGISTRATION_STATUS
我不知道该怎么做。
感谢您的宝贵时间和所有支持!
我编辑了我的脚本如下:
#!/bin/sh
echo "Please enter input file name."
read input_variable
echo "You entered: $input_variable"
echo "Please enter a name of the new output file."
touch output_file
read $output_file
echo "The output file name is going to be $output_file"
echo "Processing data extraction..." ;
awk -F": " n=25 -v 'NR<=n h[NR-1]=$1 a[NR%n-1]=$2 $1~/VENDOR/ && !hpfor(k=0;k<n;k++) printf "%s ", h[k] $input_variable && print "";hp=1 $1~/VENDOR/for(k=0;k<n;k++) printf "%s ", a[k] && print ""' data | column -t $input_variable ;
echo "Done."
这至少将数据打印到 $output_file。但是,$output_file 中的数据如下所示:
??ࡱ?;?? ????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????Root Entry????????????????????????????????????????????????????????????????
@karakfa
这是我的脚本的内容。我注意到您的答案中脚本的第一行发生了变化。因此,我将脚本修改为以下内容:
#!/bin/sh
echo "Please enter input file name."
read input_variable
echo "You entered: $input_variable"
echo "Please enter a name of the new output file."
touch output_file
read $output_file
echo "The output file name is going to be $output_file"
echo "Processing data extraction..." ;
cat $input_variable | awk -F": " -v OFS="," -v n=25
'NR<=nsub(/^ */,"",$1);h[NR-1]=$1
a[(NR-1)%n]=$2
$1~/VENDOR/ && !hpline=h[0];
for(k=1;k<n;k++) line=line OFS h[k];
print line;hp=1
$1~/VENDOR/line=a[0];
for(k=1;k<n;k++) line=line OFS a[k];
print line' $input_variable ;
echo "Done."
输出是:
Please enter input file name.
inputfile.txt
You entered: allgmail.com_accounts.txt
Please enter a name of the new output file.
outputfile.csv
The output file name is going to be
Processing data extraction...
awk: no program given
./scriptname: line 23: NR<=nsub(/^ */,"",$1);h[NR-1]=$1
a[(NR-1)%n]=$2
$1~/VENDOR/ && !hpline=h[0];
for(k=1;k<n;k++) line=line OFS h[k];
print line;hp=1
$1~/VENDOR/line=a[0];
for(k=1;k<n;k++) line=line OFS a[k];
print line: No such file or directory
Done.
我没有找到任何关于“awk: no program given”错误的文章。你知道我做错了什么吗?
我注意到上面写着“第 23 行”,所以第 23 行如下:
print line' $input_variable ;
然后,我注意到它在最后一行还写了以下内容:
print line: No such file or directory
无论有没有'cat $input_variable |'都会发生这种情况在 awk 之前。通常,awk 在我的操作系统上运行良好。它是 Mac 10.11.1 (15B42)。 #!/bin/sh 不正确吗?
我期待你的想法。谢谢!
【问题讨论】:
问题出在文件输入(编码或二进制文件),是文本文件吗? 这是一个文本文件,CSV。 你的输出很奇怪,先试试 cat "input"。然后尝试不重定向的 awk 命令>>. 【参考方案1】:为什么不在 awk 之前使用 echo ?
echo ENDOR,user_name,FIRST_NAME,LAST_NAME,CREATION_DATE,REGISTRATION_STATUS > file
【讨论】:
谢谢。对问题的其余部分有任何建议,或者您对此有任何疑问吗? 所有记录都在同一行? 记录看起来没有条理。这一行和许多其他行都有同样的问题,而其他行似乎按照他们应该做的那样做,即只有用户名、供应商、创建日期、名字、姓氏和电子邮件地址。而且,有些较短的行仍然包含毫无意义的信息。 不能说,我根据你的例子粘贴了几条记录,你的提取很完美。【参考方案2】:如果您的所有字段始终存在,您可以尝试以下awk
脚本。字段数设置为变量(在本例中为 7),“VENDOR”用作记录指示器的最后一个字段。
更新:没有注意到 csv 输出
$ awk -F": " -v OFS="," -v n=7
'NR<=nsub(/^ */,"",$1);h[NR-1]=$1
a[(NR-1)%n]=$2
$1~/VENDOR/ && !hpline=h[0];
for(k=1;k<n;k++) line=line OFS h[k];
print line;hp=1
$1~/VENDOR/line=a[0];
for(k=1;k<n;k++) line=line OFS a[k];
print line' inputfilename
user_name,EMAIL,FIRST_NAME,LAST_NAME,CREATION_DATE,REGISTRATION_STATUS,VENDOR
null@gmail.com,null@gmail.com,jonathan,doestein,2013-08-01 01:08:52,Y,vendorname
在前 n 行构建标题,完成后打印标题一次,看到最后一个字段时打印每条记录。
要将最后一个字段移到第一个,您可以将代码更改为
line=h[n-1];
for(k=1;k<n-1;k++) line=line OFS h[k];
对于这两种情况(在第二个实例中将数组名称从“h”更改为“a”)。
【讨论】:
我得到'awk:无法打开文件数据',我添加了'cat $input_variable |'在'awk -F'前面......但有同样的错误。另外,如何将其打印到 csv 文件或 $output_file,我的最后一行应该是 '> $output_file' 吗? data 是我的文件名。您必须将数据中的文件或管道替换为 awk 脚本(删除“数据”)。 我发现 'n=7' 不起作用,因为我只为 *** 打印了一定数量的数据,因为我认为这是相关的。我将编辑后的脚本添加到原始问题中。 请查看更新后的脚本。输出字段分隔符现在定义为逗号。 7 应该适用于给定的数据集。以上是关于用于从文本文件中提取数据的 Shell 脚本的主要内容,如果未能解决你的问题,请参考以下文章