ファイルの内容を置き換えるには、正規表現パターンの.shで$ 1を使用してください。

ファイルの内容を置き換えるには、正規表現パターンの.shで$ 1を使用してください。

私はあまり成功せずに努力してきました。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変数patternsumに割り当てます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つの環境変数PATTERNSTRING:

#!/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)


さらに最適化することも可能です。どんな提案でも歓迎します。

関連情報