5

アロハ、2 つのプレースホルダー間でテキスト文字列を置換/挿入する方法を見つけようとしています。

#start
REPLACE ANYTHING IN HERE
#end

もともと私はsed経由でBASHでこれをやろうとしていましたが、変数をsedに渡そうとしたときに障害にぶつかりました。

sed -n -i '/#start/{p;:a;N;/#end/!ba;s/.*\n/hello\n/};p' file.txt

戻り値

#start
hello
#end

しかし、私が試しても喜びはありません

sed -n -i '/#start/{p;:a;N;/#end/!ba;s/.*\n/$replace_var\n/};p' file.txt

また

sed -n -i "/#start/{p;:a;N;/#end/!ba;s/.*\n/$replace_var\n/};p" file.txt

私は何時間もこれに取り組んでいて、周りを検索しましたが、解決策は見つかりませんでした. 私は、python や他の言語、または awk で試してみるつもりです。私はこの分野ではちょっと新しいので、有用な情報をいただければ幸いです。

前もって感謝します

これは私が最終的に行ったものです。これは、cron と組み合わせて、公開されている最新の ssh ブロックリストで /var/etc/hosts.deny ファイルを更新するスクリプトです。

import re
import urllib2

hosts_deny = open('/etc/hosts.deny','r+')
hosts_deny_text = hosts_deny.read()

blockedHosts = urllib2.urlopen('http://www.openbl.org/lists/hosts.deny').read()
place = re.compile('(?<=#start)(\r?\n)'
                   '(.*?)'
                   '(?=\r?\n#end)',re.DOTALL)#DOTALL enables '.' to also include
                                             #a new line
hosts_deny_text = re.sub(place, '\n'+ blockedHosts, hosts_deny_text)
hosts_deny.seek(0)
hosts_deny.write(hosts_deny_text)
hosts_deny.close()
4

5 に答える 5

3

これはあなたが望むことをするようです:

sed -ie "/#start/,/#end/{/#start/b;/#end/b;s/.*/$replace_var/;}" file.txt

それ以外の場合は/#start/b/#end/bそれらも置き換えます。

于 2013-02-28T23:13:23.493 に答える
2

あなたが説明したことを考えると、私はこの単純なコードしか提案できません:

import re

ss = '''qslkjqskqsdhf
#start
REPLACE ANYTHING IN HERE
#end
2135468761265
'''

reg = re.compile('(?<=#start)(\r?\n)'
                 '(.*?)'
                 '(?=\r?\n#end)',re.DOTALL)

print ss
print '----'
print reg.sub('\\1Ia orana',ss)

結果

qslkjqskqsdhf
#start
REPLACE ANYTHING IN HERE
#end
2135468761265

----
qslkjqskqsdhf
#start
Ia orana
#end
2135468761265
于 2013-02-28T23:06:48.863 に答える
0

ファイルを文字列に読み込んでから、次の操作を実行できます。

sstart = s.split(start)
for i in range(len(s)):
   if i%2 ==1:
      send = sstart[i].split(end)
      for i in range(len(send)):
           if i%2 == 0:
                send[i] = REPLACEMENT
      sstart[i] = send.join()
s = sstart.join()

つまり、基本的にリストを確認し、交換が必要なパーツを切り取ってから、パーツを接着して戻します。

于 2013-02-28T23:06:07.380 に答える
0

このタスクにはかなり不適切だと思いますsed。代わりに awk を使用します。

awk '!f; /#start/ { f=1; print repl } /#end/ { f=0; print }' repl="$replace_var" file.txt

変数は、fマーカー内にいるときを追跡するフラグです。!fデフォルト ブロック ( {print $0}) を呼び出し、マーカーを含むマーカーの外側のすべてを出力し#startます。

テスト

eyquem の回答からコピーされたテストファイル:

cat << EOF > file.txt
qslkjqskqsdhf
#start
REPLACE ANYTHING IN HERE
#end
2135468761265
EOF

hello\nhelloマーカー間コンテンツを次のように置き換えます。

awk '!f; /#start/ { f=1; print repl } /#end/ { f=0; print }' repl="$(printf 'hello\nhello')" file.txt

出力:

qslkjqskqsdhf
#start
hello
hello
#end
2135468761265
于 2013-02-28T23:55:57.353 に答える
0

「dotall」正規表現を使えば、これは簡単です。これらは、Perl、Python、PCRE などで簡単に実行できます。たとえば、Python では次のようになります。

>>> s = '''#start
... REPLACE ANYTHING IN HERE
... #end'''
>>> re.sub(r'(?s)(#start\n).*?\n(#end)',
           r'\1hello\n\2', s)
'#start\nhello\n#end'

明らかに、開始行と終了行を一致させてそれらを置き換えるのはやり過ぎですが、さらに拡張したい場合に備えて、一般的なものにしておくことにしました。

(?s)フラグを渡す代わりにを使用したre.DOTALLので、すべてが自己完結型になり、Perl、Python などのフラグの渡し方の違いについて考える必要がなくなりました。しかし実際には、通常、フラグを埋め込むよりもフラグを使用した方が読みやすくなります。

于 2013-02-28T23:11:49.407 に答える