为模式之间的文本创建新文件
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
您可以尝试使用 perl 并借助一些有用的模块,例如 File::Path
和 File::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
我的 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
您可以尝试使用 perl 并借助一些有用的模块,例如 File::Path
和 File::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