2

誰かがこれを手伝ってくれますか? 検索パターン ( START& END) の間のすべての行を別のファイルに出力したい (new_file_name任意の増分名を指定できます)

ただし、検索パターンはファイル内で繰り返されるため、パターンが見つかるたびに、それらの行を別のファイルにダンプする必要があります

ファイルはこのようなものです

START --- ./body1/b1
##########################

123body1
abcbody1

##########################
END --- ./body1/b1

START --- ./body2/b2
##########################

123body2
defbody2

##########################
END --- ./body2/b2
4

7 に答える 7

1

パールソリューション、

perl -MFile::Basename -MFile::Path -ne '
  ($a) = /^START.+?(\S+)$/;
  $b = /^END/; 
  $a..$b or next; 
  if ($a){ mkpath(dirname $a); open STDOUT,">",$a; }
  $a||$b or print;
' file
于 2013-08-13T07:03:01.030 に答える
1

自動生成された増分ファイル名を取得するには:

awk '
/^END/   { inBlock=0 }
inBlock  { print > outfile }
/^START/ { inBlock=1; outfile = "outfile" ++count }
' file

入力のファイル名を使用するには:

awk '
/^END/   { inBlock=0 }
inBlock  { print > outfile }
/^START/ {
    inBlock=1
    outdir = outfile = $NF
    sub(/\/[^\/]+$/,"",outdir)
    system("mkdir -p \"" outdir "\"")
}
' file

@JamesBond が以下に抱えていた問題は、sub() の文字リスト内で「/」をエスケープしていなかったため、上記の回答を更新して今それを行うようにしました。エスケープする必要がある理由はまったくありませんが、どうやら nawk と /usr/xpg4/bin/awk の両方でエスケープする必要があるようです:

$ cat file
the
quick/brown
dog

$ gawk '/[/]/' file
quick/brown

$ nawk '/[/]/' file
nawk: nonterminated character class [
 source line number 1
 context is
         >>> /[/ <<< ]/

$ /usr/xpg4/bin/awk '/[/]/' file
/usr/xpg4/bin/awk: /[/: [ ] imbalance or syntax error  Context is:
>>>     /[/     <<<

そして gawk はどちらの方法でも気にしません:

$ gawk --lint --posix '/[/]/' file
quick/brown

$ gawk --lint '/[/]/' file        
quick/brown

$ gawk --lint --posix '/[\/]/' file
quick/brown

$ gawk --lint '/[\/]/' file        
quick/brown

バックスラッシュを文字リストに入れずにエスケープすると、それらはすべて正常に機能します。

$ /usr/xpg4/bin/awk '/\//' file    
quick/brown

$ nawk '/\//' file             
quick/brown

$ gawk '/\//' file
quick/brown

ですから、将来の移植性のために覚えておく価値があると思います!

于 2013-08-13T12:30:33.283 に答える
0

これを見る必要があると思います。

perl -lne 'print if((/START/../END/) and ($_!~/START/ and $_!~/END/))' your_file

以下でテスト:

> cat temp
START --- ./body1
##########################

123body1
abcbody1

##########################
END --- ./body1

START --- ./body2
##########################

123body2
defbody2

##########################
END --- ./body2
> perl -lne 'print if((/START/../END/) and ($_!~/START/ and $_!~/END/))' temp
##########################

123body1
abcbody1

##########################
##########################

123body2
defbody2

##########################
> 
于 2013-08-13T07:06:43.523 に答える
0

これは、Bash で行う 1 つの方法です。

#!/bin/bash

[ -n "$BASH_VERSION" ] || {
    echo "You need Bash to run this script."
    exit 1
}

shopt -s extglob || {
    echo "Unable to enable extglob shell option."
    exit 1
}

IFS=$' \t\n' ## Use default.

while read KEY DASH FILENAME; do
    if [[ $KEY == START && $DASH == --- && -n $FILENAME ]]; then
        CURRENT_FILENAME=$FILENAME
        DIRNAME=${FILENAME%%+([^/])}
        if [[ -n $DIRNAME ]]; then
            mkdir -p "$DIRNAME" || {
                echo "Unable to create directory $DIRNAME."
                exit 1
            }
        fi
        exec 4>"$CURRENT_FILENAME" || {
            echo "Unable to open $CURRENT_FILENAME for output."
            exit 1
        }
        for (( ;; )); do
            IFS= read -r LINE || {
                echo "End of file reached finding END block of $CURRENT_FILENAME."
                exec 4>&-
                exit 1
            }
            read -r KEY DASH FILENAME <<< "$LINE"
            if [[ $KEY == END && $DASH == --- && $FILENAME == "$CURRENT_FILENAME" ]]; then
                break
            else
                echo "$LINE" >&4
            fi
        done
        exec 4>&-
    fi
done

スクリプトを UNIX ファイル形式で保存してから、.xml ファイルとして実行してbash script.sh < fileください。

于 2013-08-13T06:16:25.253 に答える
0

これはあなたのために働くかもしれません:

csplit -z file '/^START/' '{*}'

ファイルに名前が付けられますxx00 xx01 xx..

于 2013-08-13T07:24:45.837 に答える