2015-02-28 4 views
0

я следующий шаблоном в моем текстовом файле:Создать новый файл для текста между рисунком

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

Я хочу разделить этот файл на как (если я выдавать команду кота она должна иметь источник, за то, что в выше один файл):

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=$0;next}/java$/{flag=0}flag' source.txt 

Но не в состоянии REDIR ect код между файлом с различными несуществующими папками.

ответ

0

Я сделал следующее, так как мне пришлось сделать это срочно.

#!/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 
+0

один комментарий в быстром сканировании: используйте 'чтения -r line' иначе, обратный слеш сбежал символы будут интерпретироваться с помощью bash. (такой '\ n'). – jm666

+0

На самом деле, всегда используйте 'while IFS = read -r line', если у вас нет конкретной причины.Вы также должны всегда указывать свои переменные, чтобы отключить глобализацию и разбиение слов, или вы получите причудливые сбои на основе содержимого входного файла и имен файлов в вашем рабочем каталоге, а ваши команды sed будут терпеть неудачу с учетом различного содержимого вашего входного файла. Не делай этого! –

+1

@EdMorton true! для предотвращения удаления пробелов в пути;) – jm666

0

Вероятно, здесь более элегантное решение, но я хотел бы сделать это как:

#!/bin/bash 
[[ -f "$1" ]] || { echo "Usage: $0 filename" >&2; exit 1; } 
csplit -z -s -k -n4 -f _java_source. "$1" '/^\.\/.*\.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 ...
  • , а на втором этапе создаются финальные каталоги и файлы. Остерегайтесь, он слепо принимает шаблон как папку/имя файла без каких-либо проверок.

Для perl пользователей, (например, который, вероятно, установивших Path::Tiny модуля)

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

Вы можете попробовать и помощь некоторых полезных модулей, как File::Path и File::Spec. Первый используется для создания каталогов, таких как оболочка 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 
1

Все, что вам нужно, это что-то вроде (непроверенные, но будет очень близко, если не полностью работает):

awk ' 
/^\/\// { print > file; next } 
{ close(file); dir=file=$0; sub(/\/[^\/]+$/,"",dir); system("mkdir -p \"" dir "\"") } 
' source.txt 
Смежные вопросы