Shell

在正則表達式模式中使用 .sh 中的 $1 以替換文件中的內容

  • April 17, 2020

我一直在嘗試,但在擷取兩個單詞之間的單詞在兩個下劃線之間獲取單詞以及許多其他單詞方面沒有取得多大成功……

我想在“##”之前找到換行符,這個“##”在“## 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

我想要兩件事:1/ 用參數 $2 (變數 foo)替換 baba,2/ 在 ^## 中包含 \n 以使其在上面一行。

非常感謝您的幫助


編輯:感謝Rudic,我想出了:

a.sh

sed -re "/## $1/,/^\n\n##/ {s/^## *$/$2\n\n\n&/}" a.md

a.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}


##

也許沿著這條線:

sed '/## *baba/,/^##/ {s/^## *$/helloworld\n&/}' file

或者,如果作為參數給出,

sed "/## *$2/,/^##/ {s/^## *$/$1\n&/}" file

以下將從命令行獲取模式以及替換文本,並將它們分配給awk變數patterntext.

在該塊中,我修改了模式以在開頭BEGIN包含正則表達式。^##

然後,我使用範圍表達式觸發一段程式碼,該程式碼塊將為文件中的給定部分執行(以 開頭的部分##後跟與 original 匹配的內容pattern,直到與表達式匹配的行^##$)。

如果在該塊中,目前行恰好與表達式匹配^##$,我列印hello world使用者給出的字元串,並添加兩個額外的換行符。

所有輸入行都由最終{ print }塊列印。

如果要使用位置參數$1(用於替換文本)和$2(用於模式),請將baba以下內容替換為$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

從兩個環境變數中獲取模式和文本的替代實現:

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


根據評論中的要求,一個腳本將採用兩個參數,一個模式和一個替換字元串,或者兩個環境變數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

未能提供兩個命令行參數或兩個環境變數將導致錯誤消息並且awk程式碼根本不會執行。

引用自:https://unix.stackexchange.com/questions/580602