为模式之间的文本创建新文件

Create new file for the text between the pattern

我的 txt 文件中有以下模式:

./folder1/folder2/myfile.java
//java source line1
//java source line2
./folder1/folder3/myfile1.java
//java source line1
//java source line2
//java source line3

我想将此文件拆分成类似的文件(如果我发出 cat 命令,它应该具有上述文件中的源代码):

cat ./folder1/folder2/myfile.java
//java source line1
//java source line2

cat ./folder1/folder3/myfile1.java
//java source line1
//java source line2
//java source line3

我可以使用以下方法提取内容和文件名:

awk '/java/{flag=1;fileName=[=12=];next}/java$/{flag=0}flag' source.txt

但无法将代码重定向到具有不同的不存在文件夹的文件。

可能这里有更优雅的解决方案,但我会这样做:

#!/bin/bash
[[  -f "" ]] || { echo "Usage: [=10=] filename" >&2; exit 1; }
csplit -z -s -k -n4 -f _java_source. "" '/^\.\/.*\.java$/' '{*}'
for file in _java_source.????
do
    dir_file=$(head -1 $file)
    dir=$(dirname "$dir_file")
    echo "creating $dir_file" >&2
    mkdir -p "$dir" && tail -n +2 < $file > "$dir_file" && rm $file
done

两步解决方案:

  • 在第 1 步中,csplit 以模式 ./(anything).java 拆分输入文件并创建文件 _java_source.0001...
  • 并在第二步中创建最终的目录和文件。当心,它盲目地接受模式 folder/filename 而不进行任何检查。

对于 perl 用户,(例如可能安装了 Path::Tiny 模块的用户)

perl -MPath::Tiny -0777 -lnE '$r=qr(\./.*?\.java);path()->touchpath->spew()while(m{($r)\n(.*?)(?=($r|\z))}gs)' < file

您可以尝试使用 并借助一些有用的模块,例如 File::PathFile::Spec。第一个用于创建目录,如 shell mkdir -p,第二个用于处理提取目录的路径和要写入的文件。剩下的就是使用正则表达式来检查一行是否以 .java 结尾,并创建文件或写入文件。

#!/usr/bin/env perl

use strict;
use warnings;
use File::Path qw<make_path>;
use File::Spec;

my ($fh);

while (<>) {
    chomp;
    if (m/\.java\z/) {
        $_ = File::Spec->rel2abs($_);
        my $dir = File::Spec->catdir((File::Spec->splitpath($_))[0,1]);
        make_path($dir, { error => \my $e }); 
        if (@$e) {
            printf qq|Error creating path: %s\n|, $dir;
            exit 1;
        }   
        close $fh if defined $fh;
        open $fh, '>', $_ or die qq|Cannot open file: $_\n|, $_; 
    } else {
        printf $fh qq|%s\n|, $_; 
    }   
}

您可以 运行 它以输入文件作为参数,例如:

perl script.pl infile

并检查结果:

find ./folder1 -type f -iname '*.java' -exec head '{}' \+

结果:

==> ./folder1/folder3/myfile1.java <==
//java source line1
//java source line2
//java source line3

==> ./folder1/folder2/myfile.java <==
//java source line1
//java source line2

我做了以下因为我必须紧急做。

#!/bin/bash
lastLine="2"
while read line
do
    if [[ $lastLine == "2" ]]
    then
       end=100
       lastLine=$line
       continue
    fi
    dir=$(dirname $lastLine)
    mkdir -p $dir
    source=$(echo $lastLine | sed 's/\//\\//g')
    dest=$(echo $line | sed 's/\//\\//g')
    sed -n "/$source/,/$dest/p" qpr_code.txt > $lastLine
    sed -i '1d;$d' $lastLine
    lastLine=$line
done < mytest.txt

你所需要的只是类似的东西(未经测试,但如果不能完全工作,将非常接近):

awk '
/^\/\// { print > file; next }
{ close(file); dir=file=[=10=]; sub(/\/[^\/]+$/,"",dir); system("mkdir -p \"" dir "\"") }
' source.txt