複数行に渡っても括弧の間にある内容を変更してください。

複数行に渡っても括弧の間にある内容を変更してください。

Bashまたはシェルスクリプトを使用して交換したい何もない2つの括弧の間にスペースがあります。 2つの括弧の間のテキストは複数行にすることができます。たとえば、次のようになります。

myFunction (line0

line1

line2

line3

line4) 

次に変換したいです。

myFunction ( )

答え1

@Sergの答えを受けbashて、1行に2〜3つのプロセスの代わりにbash組み込み機能を使用するように変換します。このプロセスは安いですが、無料ではありません!

#!/bin/bash
# Use shell builtins, read, true, false, printf
flag=false
while IFS= read -r line
do
    case "$line" in
    (*"("*) flag=true ;;
    esac

    if $flag
    then
        line=${line//line/newline} 
    fi

    printf "%s\n" "$line"

    case "$line" in
    (*")"*) flag=false ;;
    esac

done < "$1"

答え2

AWK

{}AWKを使用すると、さまざまな条件でコードブロックを実行できます。この場合、gsub()Contains(からContainsまでの行の範囲で各行を実行しようとします)

$ awk '$0~/[(]/,$0~/[)]/{gsub(/line/,"newline")};1' input.txt                                                     
another line
something else

myFunction (newline0

newline1

whatever

newline2

newline3

newline4)

some other line

Python(元の答え)

以下は、タスクを実行するクイックPythonスクリプトです。

#!/usr/bin/env python3
from __future__ import print_function
import sys

with open(sys.argv[1]) as fp:
    flag = None
    for line in fp:
        clean_line = line.strip()
        if "(" in clean_line: flag = True
        if flag:
           clean_line = clean_line.replace("line","newline")
        print(clean_line) 
        if ")" in clean_line: flag = False

テスト実行:

$ cat input.txt                                                                                                          
another line
something else

myFunction (line0

line1

lilne2

line3

line4)

some other line
$ ./edit_function_args.py input.txt                                                                                      
another line
something else

myFunction (newline0

newline1

newline2

newline3

line4)

some other line

バッシュバージョン

bash次のように書き直されたことを除いて、同じスクリプトsed

#!/bin/bash
flag=false
while IFS= read -r line
do

    if grep -q '('  <<< "$line"
    then
        flag=true 
    fi


    if $flag
    then
        line=$(sed 's/line/newline/'   <<< "$line") 
    fi

    printf "%s\n" "$line"


    if grep -q ')'  <<< "$line"
    then
        flag=false     
    fi

done < "$1"

答え3

perl回避策が大丈夫で、ファイルが全体的に処理されるほど小さい場合:

$ perl -0777 -pe 's/\([^)]+\)/$&=~s|line|newline|gr/ge' ip.txt    
myFunction (newline0

newline1

newline2

newline3

newline4) 
  • -0777完全な入力ファイルを食べる
  • \([^)]+\)一致させるパターン - 文字(以外の文字が続き、)次に終了します。)
  • $&=~s|line|newline|gr引用したパターンがここで使用され、$&必要な置換(改行から改行)が行われます。r結果を代替文字列として返すフラグに注意してください。
  • eフラグを使用すると、文字列の代わりに式を使用できます。
  • perl -i -0777 -pe内部編集用

答え4

使用awk:
awk '
  function mysub(str) {
    if (str) gsub(/line/, "newline", str); return str
  }
  BEGIN {
    OFS=FS="("
  }
  NF>1 {
    if (FS=="(") {
      print $1,mysub($2); OFS=FS=")"
    } else {
      print mysub($1),$2; OFS=FS="("
    }
    next
  }
  {
    print FS=="(" ? $0 : mysub($0)
  }' /path/to/input

ユーザー定義関数は、mysub角かっこの間に必要な置換を実行する場所です。角かっこが入れ子になっていないとします。

仕組み:

括弧の内側と外側の括弧の2つの状態があります。

  • 外部では、(開始状態)入力と出力の区切り文字は左角括弧(OFS=FS="(")に設定されます。
  • 入力区切り記号()でNF>1区切られた複数のフィールドを含む行に出会うと...
    • ...現在、外部モード()にあり、FS=="("フィールド区切り記号の前後のすべての内容が出力されますが(出力区切り記号は中央にあります)、後者は代替機能(mysub($2))を介してモードと出力区切り記号を反転します。入力記号(OFS=FS=")")を変更して、
    • ...そうでなければ(else)内部モードにあり、フィールド区切り記号の前後のすべての内容が出力されますが、今回は前者が代替機能(mysub($1))を経てここでもモードが反転されます。
  • 他のすべてのラインで外部()の場合、ライン全体は変更されずに出力され、FS=="("それ以外の場合は代替関数()を介して全体に渡されますmysub($0)
一行にまとめると次のようになります。
awk 'function m(s){gsub(/line/,"newline",s);return s}BEGIN{OFS=FS="("}NF>1{if(FS=="("){print $1,m($2);OFS=FS=")"}else{print m($1),$2;OFS=FS="("}next}{print FS=="("?$0:m($0)}' /path/to/input
私のトリッキーなテストデータ(ここでいくつかの1行のソリューションは失敗します):
line96
line97 myFunction (line0

line1

line2

line3

line4) line98
line99
出力:
line96
line97 myFunction (newline0

newline1

newline2

newline3

newline4) line98
line99
角かっこの間のすべての内容を削除するバリアントです(最初の行と最後の改行を除く):
awk '
  BEGIN {
    OFS=FS="("
  }
  NF>1 {
    if (FS=="(") {
      print $1,""; OFS=FS=")"
    } else {
      print "",$2; OFS=FS="("
    }
    next
  }
  FS=="("' /path/to/input
この出力は次のようになります。
line96
line97 myFunction (
) line98
line99

関連情報