用于从文本文件中提取数据的 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 脚本的主要内容,如果未能解决你的问题,请参考以下文章

从文本文件中查找和提取数据

shell 脚本里面从一个文本里面读出一个数字,如何转换成整数?我需要用这个数字进行加减乘除

Linux Shell脚本入门--cut命令

Linux Shell脚本编程--cut命令

Linux Shell脚本编程--cut命令

请教一个批量删除文本文件中多余回车或提取文本中前两行数据的shell脚本,请高手指点,万分感谢