web-dev-qa-db-ja.com

2つのシンボル間のテキスト範囲を編集するにはどうすればよいですか? awk、sed、regex

「*」記号を使用して(その記号である必要はなく、特殊文字を使用して指示します)、これからテキストを編集するにはどうすればよいですか。

*berry
straw
rasp
blue
boysen
*
blahblah
blahblah
blahblah
*berry
straw
blue
*
blah
*table
vege
pingpong
*

これに:

strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable

最初に一致するアスタリスクの後のすべての文字は、2番目のアスタリスクが見つかるまですべての行に配置されます。

私はこれについてどうやって行くことができますか? (sedまたはawkをお勧めしますが、別の方法が考えられる場合は、コードを教えてください!)

私はアスタリスクを含むすべての行を削除する方法を知っています、それは私が考えることができない文字配置部分です

6
TuxForLife

このawkコードで十分です:

awk -F'*' 'NF == 2 {label = $2; next} {$0 = $0 label} 1'

分解するには:

  • フィールド区切り文字として*を使用します。この方法で、フィールドの数(NF)を単純に調べて、ブロックの先頭または末尾に到達したかどうかを判断できます。
  • 2つのフィールドがある場合、2番目のフィールドをlabelに保存し、次の行に進みます。
  • それから、そのlabelを現在の行に追加してから印刷します。ラベルが空の場合、ブロックの外側にいるため、効果はありません。そうでない場合、必要な出力を取得します。
12
muru

sedでは、削除する前に「特別な」行を保留スペースにコピーできます

sed -e '/^\*/{h;d;}'

ホールドスペースを後続の各パターンスペースに追加し、結果の改行文字とマーカー文字を置き換えます

    -e '{G;s/\n\*//;}'

あなたのデータでテストし、

$ sed -e '/^\*/{h;d;}' -e '{G;s/\n\*//;}' file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable

注:これは、2番目のアスタリスクが検出されても停止しません。まったく同じですが、次の*に一致するまで*sometextの後に何も付加されません。

8
steeldriver

Perlの方法は次のとおりです。

$ Perl -lne '/^\*(.*)/ || print "$_$1"' file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable

説明

-nはPerlに入力ファイルの各行を読み取らせ、特殊変数$_に保存します。-lはi)後続の改行(\n)各行からii)printの各呼び出しに改行を追加します。 -eは、各行に適用されるスクリプトです。

  • /^\*(.*)/:アスタリスクで始まる行に一致し、アスタリスクの後のすべてを$1として保存します(括弧が行うことです)。

  • || print "$_$1"'||は論理的なORです。したがって、printは、現在の行がアスタリスクで始まっていない場合にのみ実行されます。その場合、現在の行($_)を、現在$1(アスタリスクに続くパターン)として保存されているものと一緒に印刷します。


いつものように、これを行うには多くの方法があります。愚かで非効率的なものですが、シェルの文字列操作機能を強調するものは次のとおりです。

$ while read line; do 
    [[ $line =~ ^\* ]] && pat="${line#\*}" || printf "%s%s\n" "$line" "$pat"; 
  done < file
strawberry
raspberry
blueberry
boysenberry
blahblah
blahblah
blahblah
strawberry
blueberry
blah
vegetable
pingpongtable

説明

  • while read line; do ... ; done < file:これは、入力ファイルwhileの各行を読み取り、$lineとして保存する古典的なfileループです。
  • [[ $line =~ ^\* ]] && pat="${line#\*}":行が*で始まる場合、その後のすべてを削除します(これは${line#\*}が行うことです。詳細については here を参照)、保存してください$patとして。 * || printf "%s%s\n" "$line" "$pat";:前のコマンドが失敗した(したがって、行がアスタリスクで始まらない)場合、行と$patの現在の値を出力します。

7
terdon

私の好きなPythonを通して...

with open('/path/to/the/file') as f:
    counter = False
    for line in f:
        if line.startswith('*') and not counter:
            m = line.strip().lstrip('*')
            counter = True
        Elif line.startswith('*') and counter:
            counter = False    
        Elif counter:
            if not line.startswith('*'):
                print(line.strip() + m)
        else:
            print(line.strip())  
3
Avinash Raj

遅く来た。別のpythonアプローチがあります。

#!/usr/bin/env python2
with open('/path/to/file.txt') as f:
    for lines in f.read().split('*'):
        entries = lines.rstrip().split('\n')
        for i in range(1, len(entries)):
            print entries[i] + entries[0]
3
heemayl