Bashまたはシェルスクリプトを使用して、2つの括弧の間のanythingを空白スペースに置き換えます。 2つの括弧の間のテキストは、次のように複数行になる場合があります。
myFunction (line0
line1
line2
line3
line4)
私が変換したいもの:
myFunction ( )
AWKでは、条件の範囲でコードブロック_{}
_を実行できます。この場合、_(
_を含む行から_)
_を含む行までの範囲内のすべての行でgsub()
を実行します。
_$ awk '$0~/[(]/,$0~/[)]/{gsub(/line/,"newline")};1' input.txt
another line
something else
myFunction (newline0
newline1
whatever
newline2
newline3
newline4)
some other line
_
ここに簡単な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"
_
@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"
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
_を使用します最初に提示された質問とデータについては、sed 1ライナーが機能します
sed '/(/,/)/s/line/newline/g'
これは、(
を含む行で始まり、 ')'を含む行で終わる各リージョンについて、line
をグローバルにnewline
に置き換えます。入力行の最初のg
のみを変更する場合は、line
を削除します。
変更された質問については、
sed -e '/(/{' -e ':loop;s/(.*)/()/;t;N;b loop' -e '}'
動作します。入力をループし、(
が見つかるまで出力します。この時点で、区切り文字を含む(
)
ペア内のすべてを()
だけに変更しようとします。これが成功すると、ループから抜け出し、結果を出力して続行します。通常は)
をまだ認識していないために、それがうまくいかなかった場合は、次の入力行を追加してループを続行します。 1行にしたくない場合は、次のように記述します。
sed -e '/(/{
:loop
s/(.*)/()/
t
N
b loop
}'
フォローしやすくなります。
ネストされた括弧も正しく処理したい場合は、 sgrep のように、通常の言語ではなく、文脈自由言語用のツールを使用します。
sgrep -o '%r ' '(start .. end) extracting ("("__")")' < input_file
このように、たとえば、次の
myFunction (line0
line1
(line2)
line3
line4)
anotherFun (x y)
なる
myFunction ( )
anotherFun ( )
明確化、コメント、改訂されたデータをすべて組み合わせると、私の申し出は次のようになります。
まず最初に、アドバイスされたmyFunction (...)
ともう1つの関数を含むソースファイル_d.txt
_をより現実的にすることを検討してみましょう。
ハードサイドになるために、このd.txtファイル内の2つの関数の内容が次のようにほぼ同じであると仮定します。
_$ cat d.txt
myOtherFunction (x as boolean
y as integer
d as string
e as whatever)
myFunction (xx as boolean
yy as integer
dd as string
ee as whatever)
_
別のファイル_d2.txt
_に別の関数があるとしましょう。
_$ cat d2.txt
BrandNewFunction (xxx as integer
yyy as boolean
ddd as integer
eee as whatever)
_
Line、newlineなどのサンプル名を忘れて、コメントを検討すると、最初のソースコードファイル_d.txt
_既存のmyFunction (..)
をBrandNewFunction (...)
ファイル_d2.txt
_に存在します。
これは、純粋なbashを使用して簡単に行うことができます。
_$ a="$(sed -n '/myFunction (/,/)/p' d.txt)" #isolates myFunction from the source file d.txt
$ b="$(cat d2.txt)" #get contents of file d2.txt (BrandNewFunction)
$ c="$(cat d.txt)" #get the whole source file d.txt
$ echo "${c/$a/$b}" #in source file d.txt ($c) replace $a with $b (d2.txt)
#Output:
myOtherFunction (x as boolean
y as integer
d as string
e as whatever)
BrandNewFunction (xxx as integer
yyy as boolean
ddd as integer
eee as whatever)
_
またはワンライナーとしても:
_$ a="$(sed -n '/myFunction (/,/)/p' d.txt)";b="$(cat d2.txt)";c="$(cat d.txt)";echo "${c/$a/$b}"
_
上記のコマンドは、置換結果(エコー)を画面に出力するだけです。結果を保存するには、エコーを_>d.txt
_に送信して、既存のファイルまたは必要に応じて新しいファイルを上書きします。
Sedは行の操作に焦点を当てているため、改行で区切られた複数の行を置き換えるのはあまり良くないようです。
AWKは仕事に適していますが、AWKは得意ではありません。
Bashは、マルチラインを正常に置き換えることができる最も簡単なソリューションです。
PS1:ファイル_d2.txt
_にさらに関数が含まれていて、ソースファイル_d.txt
_と同様にBrandNewFunction (..)
を分離する場合は、$ b変数定義を次のように変更するだけです。
_$ b="$(sed -n '/BrandNewFunction (/,/)/p' d2.txt)"
_
PS2:ソースファイルd.txtのmyFunction(...)を同じ名前の空白の関数に置き換えるだけの場合は、変数bを次のようにハードコードできます(ソースファイルd.txtのどの関数を使用するかはすでにわかっています)削除しますか?)
_$ b="myFunction ( )"
_
GNUの新しいバージョンsedは-zオプションをサポートしています。
通常、sedは、行末文字(改行または改行)までの文字列を読み取ることによって行を読み取ります。
GNU sedのバージョンは、バージョン4.2.2で「NULL」文字を使用する機能を追加しました。これは、NULLを使用するファイルがある場合に役立ちます。一部のGNUユーティリティは、「find。-print0」や「grep -lZ」など、新しい行の代わりにNULLを使用する出力を生成できます。
このオプションは、sedを別の行で動作させたい場合に使用できます。
sed -z 's/([^)]*)/( )/g' inputfile