
私はあまり成功せずに努力してきました。2 つの単語間の単語のキャプチャそして2つの下線の間にある単語を探す他の多くの中で...
「##」の前の改行文字を探したいです。この「##」は「## baba」の後に続きます。しかし、その直後にはなく、その間にいくつかのテキストがあります。ファイルには常に \n が先行する「##」がたくさんあります。以下のスキーマを参照してください。
希望の出力
##
## baba {could also be "foo" or "bar"}
rosa rosa rosam rosae ipsum
{append or replace the '\n' before '\n##' with -> helloworld here}
##
##
見つけたら、「helloworld」をスクリプトに引数として挿入します。
私の現在のスクリプトは次を探します。
awk -i inplace -v foo=$2 -v new=$1'\n\n' 'f&&/^##/{print new; f=0} {print} /^## baba/{f=1}' a.md
私は2つのことをしたいと思います:1 / babaをパラメータ$ 2(変数foo)に置き換え、2 / \ nを^##でラップして1行上にします。
助けてくれてありがとう
編集:Rudicのおかげで、次のことを見つけました。
禁煙健康増進協会
sed -re "/## $1/,/^\n\n##/ {s/^## *$/$2\n\n\n&/}" a.md
MD
##
## baba
rosa rosa rosam rosae ipsum
##
##
コマンドライン
cat a.md && echo "---------------" && ./test.sh baba remember140416sewol
ただし、出力には2つの欠陥があります。 1/は各一致に対して作成され、最初の一致のみが必要です。2/は他の改行の前に新しい行を置き換えません。
##
## baba
rosa rosa rosam rosae ipsum
{\n <-extra new line}
remember140416sewol
##
remember140416sewol {<-- extra occurence}
##
答え1
次のように見えます。
sed '/## *baba/,/^##/ {s/^## *$/helloworld\n&/}' file
または引数で与えられた場合、
sed "/## *$2/,/^##/ {s/^## *$/$1\n&/}" file
答え2
以下は、コマンドラインから代替テキストとともにパターンを取得し、awk
変数pattern
sumに割り当てますtext
。
このブロックでは、先頭に正規表現を含めるBEGIN
ようにパターンを変更します。^##
次に、範囲式を使用して、文書の指定されたセクションに対して実行されるコードブロックをトリガーします(セクションから始まり、##
元のものと一致するものからpattern
式と一致する行まで^##$
)。
そのブロック内で現在の行が式と一致する場合は、指定した文字列を^##$
印刷し、2つの改行を追加します。hello world
すべての入力ラインは{ print }
最後のブロックによって印刷されます。
$1
位置引数(代替テキストの場合)と$2
(パターンの場合)を使用するには、baba
次を$2
とに置き換えます。同様に、代替テキストとパターンを保存する他の2つの変数がある場合も同様です。hello world
$1
awk -v pattern="baba" -v text="hello world" '
BEGIN { pattern = "^## " pattern }
$0 ~ pattern,/^##$/ { if (/^##$/) print text "\n\n" }
{ print }' a.md
別の実装は、2つの環境変数からパターンとテキストを取得することです。
PATTERN="baba" TEXT="hello world" awk '
BEGIN { pattern = "^## " ENVIRON["PATTERN"] }
$0 ~ pattern,/^##$/ { if (/^##$/) print ENVIRON["TEXT"] "\n\n" }
{ print }' a.md
質問の最後にある文書を考慮すると、次の結果が生成されます。
##
## baba
rosa rosa rosam rosae ipsum
hello world
##
##
変数を介したデータ転送に関連するawk
:
〜のようにコメントで尋ねる、パターンと置換文字列の2つのパラメータを使用するスクリプト、または2つの環境変数PATTERN
とSTRING
:
#!/bin/sh
if [ "$#" -eq 0 ]; then
# No arguments given.
# Take pattern and string from environment.
pattern=${PATTERN:?missing}
string=${STRING:?missing}
else
# Arguments given.
# Take pattern and string from 1st and 2nd argument.
pattern=${1:?argument 1 (pattern) missing}
string=${2:?argument 2 (string) missing}
fi
# Either of the two `awk` commands from above would work,
# with $pattern and $string inserted in the appropriate
# command line arguments to awk:
awk -v pattern="$pattern" -v text="$string" '
BEGIN { pattern = "^## " pattern }
$0 ~ pattern,/^##$/ { if (/^##$/) print text "\n\n" }
{ print }' a.md
これは次のように実行できます。
./script.sh 'baba' 'hello world'
または
export PATTERN='baba' STRING='hello world'
./script.sh
2つのコマンドライン引数または2つの環境変数を指定しないと、エラーメッセージが表示され、コードはawk
まったく実行されません。
答え3
私は私が望むことを正確に行う非常に便利なPythonスクリプトを使ってこの問題を直接解決しました。
import sys
import os
import re
topic = sys.argv[1]
pattern = "## " + topic
s = r"cat a.md | grep -n '" + pattern + "' a.md | awk -F ':' '/0/ {print$1}'"
#print(s)
pattern = re.compile("##")
stream = os.popen(s)
lineNb = int(stream.read().rstrip())
filename="a.md"
with open(filename, "r") as f:
for _ in range(lineNb):
next(f)
for line_i, line in enumerate(f, 1):
if re.search(pattern, line):
index = line_i + lineNb - 1
#print( "%d\n" % index )
break
with open(filename, "r") as f:
contents = f.readlines()
contents.insert(index - 1, sys.argv[2] + "\n\n")
with open(filename, "w") as f:
contents = "".join(contents)
f.write(contents)
さらに最適化することも可能です。どんな提案でも歓迎します。