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