根据第一列中的名称外观将文件拆分为多个文件

时间:2018-01-17 23:23:10

标签: awk split multiple-files

如何将file.txt拆分为子文件,其中每个文件在file.txt中的连续外观为XX?例如打印行以XX开头进入file1.txt,如果下一行不是XX则关闭file1.txt并打开file2.txt以便下次出现XX。

输入文件:file.txt

nav a {
text-decoration: none;
color: black;
align-items: center;
overflow: hidden;
padding-left: 20px;
/* =========================== this is where it fixes 
the problem but creates another one =======*/
position: absolute;  
}

nav {
background-color: #ffffff;
height: 75px;
}

nav li {
list-style: none;
position: relative;
text-decoration: none;
padding: 2%;
align-items: center;
overflow: hidden;
float: right;
display: inline;
}

nav img {  
margin-top: .8%;
margin-left: 2%;
height: 50px;
width: auto;
position: relative;
}

<nav>                      
<img src="bowtie.png" href="index.html"> 
<span><a href="index.html" class="homenav">Home</a></span>             
<li><a href="#contact">Contact Us</a></li>
<li><a href="about.html">About Us</a></li>
<li><a href="photos.html">Products</a></li>                  
</nav>

期望的输出:

file1.txt

some header information
XX 123 456 abc
XX 234 567 def
XX 456 345 ghi
END
XX 345 654 ijk
XX 567 789 klm
XX 678 asd mno
XX 567 thy mnb
YY 123 dft fty
XX 456 tfg tyg 
XX 456 thu gtr 
PAGE2
XX 345 dcf try

FILE2.TXT

XX 123 456 abc
XX 234 567 def
XX 456 345 ghi

file3.txt

XX 345 654 ijk
XX 567 789 klm
XX 678 asd mno
XX 567 thy mnb

file4.txt

XX 456 tfg tyg 
XX 456 thu gtr

3 个答案:

答案 0 :(得分:3)

使用awk,单行:

$ awk '!/^XX/{if(f)close(f);f=sprintf("file%d.txt",++n);next}{print >f}' infile

<强>解释

awk '!/^XX/{                          # if line/record/row does not start with XX
         if(f)                        # if variable f was set before
            close(f);                 # close file 
         f=sprintf("file%d.txt",++n); # pre increment variable n, generate new file name
         next                         # go to next line
      }
      {
         print >f                     # Records starts with XX will be
                                      # written to file defined in variable f
      }
     ' infile

测试结果:

<强> 输入:

$ cat infile
some header information
XX 123 456 abc
XX 234 567 def
XX 456 345 ghi
END
XX 345 654 ijk
XX 567 789 klm
XX 678 asd mno
XX 567 thy mnb
YY 123 dft fty
XX 456 tfg tyg 
XX 456 thu gtr 
PAGE2
XX 345 dcf try

<强> 输出:

$ cat file1.txt 
XX 123 456 abc
XX 234 567 def
XX 456 345 ghi

$ cat file2.txt 
XX 345 654 ijk
XX 567 789 klm
XX 678 asd mno
XX 567 thy mnb

$ cat file3.txt 
XX 456 tfg tyg 
XX 456 thu gtr 

$ cat file4.txt 
XX 345 dcf try

征求意见:

  

如果输入文件的标题信息中有太多行,   输出文件名以较大的数字开头。我怎么能开始   来自ouput1.out的输出文件等等?

awk '/^XX/{if(!w)f=sprintf("file%d.txt",++n);w=1;print >f;next}{close(f);w=0}' infile

<强>解释

awk '/^XX/{                             # if line starts with XX
        if(!w)                          # if negate of w is true
           f=sprintf("file%d.txt",++n); # pre increment n, and set up variable f 
        w=1;                            # set variable w = 1
        print >f;                       # write record/row/line to file
        next                            # go to next line
     }
     {                                  # for which does not start with XXX  
        close(f);                       # close file
        w=0                             # set w = 0, (so that for next line with XX use newfile)
     }
    ' infile

测试结果 - 评论:

输入修改:

$ cat infile 
some header information
some header2
some header 3
XX 123 456 abc
XX 234 567 def
XX 456 345 ghi
END
some more extra
wxxasa
extrasa
XX 345 654 ijk
XX 567 789 klm
XX 678 asd mno
XX 567 thy mnb
YY 123 dft fty
XX 456 tfg tyg 
XX 456 thu gtr 
PAGE2
XX 345 dcf try

执行:

$ awk '/^XX/{if(!w)f=sprintf("file%d.txt",++n); w=1;  print >f;next}{close(f); w=0}' infile 

生成的文件:

$ ls *.txt -1
file1.txt
file2.txt
file3.txt
file4.txt

每个文件的内容:

$ for i in *.txt; do echo "File: $i"; cat $i; done
File: file1.txt
XX 123 456 abc
XX 234 567 def
XX 456 345 ghi
File: file2.txt
XX 345 654 ijk
XX 567 789 klm
XX 678 asd mno
XX 567 thy mnb
File: file3.txt
XX 456 tfg tyg 
XX 456 thu gtr 
File: file4.txt
XX 345 dcf try

答案 1 :(得分:1)

关注T也可以帮助您。

awk

它将创建4个输出文件,如下所示。

awk '!/^XX/{delete a[XX];if("file"val".txt"){close("file"val".txt")};next} FNR>1 && !a[XX]++{val++} /^XX/{print > "file"val".txt"}' Input_file

上面是在GNU -rw-rw-r-- 1 singh singh 15 Jan 17 22:29 file4.txt -rw-rw-r-- 1 singh singh 32 Jan 17 22:29 file3.txt -rw-rw-r-- 1 singh singh 60 Jan 17 22:29 file2.txt -rw-rw-r-- 1 singh singh 45 Jan 17 22:29 file1.txt 中编写和测试的,如果您没有GNU awk,您也可以从awk更改为delete a[XX]。我现在也会为此添加解释。

编辑: 此处还添加了非单行形式的解决方案以及解释。

for(num in a){delete a[num]}

答案 2 :(得分:0)

您可以使用以下awk命令处理文件并生成输出文件:

awk 'BEGIN{file_cmpt=1}{if($1=="XX"){print $0 > "output"file_cmpt".out";}else{file_cmpt++}}' input.txt

<强>解释

  • BEGIN{file_cmpt=1}将文件计数器初始化为1
  • {if($1=="XX"){print $0 > "output"file_cmpt".out";}如果第一列是XX,则将其打印到当前文件
  • else{file_cmpt++}如果第一行第一个字段与XX不同,则将其打印到另一个文件

测试您的输入文件:

enter image description here

如果您在输入文件的顶部有一些标题信息,则可以使用以下awk命令:

awk 'BEGIN{file_cmpt=1;in_header=1}{if($1=="XX"){print $0 > "output"file_cmpt".out";in_header=0}else{if(!in_header){file_cmpt++}}}' input.txt

唯一的变化是我在递增文件计数器之前添加了一个in_header测试条件。 (我们假设最初我们在文件的标题部分,当我们遇到第一次出现XX时,我们将this的值设置为0,我们可以在达到a时立即开始递增计数器第一个字段不等于XX的行。

测试了以下输入:

enter image description here