[英]How do I replace a string with a newline using a bash script and sed?
[英]Replacing dates in bash script using sed: phantom newline error
因此,我正在嘗試使用 bash 中的 sed 對文檔元數據中的日期進行簡單的正則表達式替換。 例如,假設我有輸入文件test.md
包含:
---
title: "I am a file"
date: December 1, 2021
---
Loren ipsum blah blah blah
我希望能夠在 12 月 29 日運行 bash 腳本並獲得 output 文件
---
title: "I am a file"
date: December 29, 2021
---
Loren ipsum blah blah blah
所以這是我的第一次嘗試:
#!/bin/bash
TODAY=$(date +'%B %d, %Y')
STARTBIT="date: "
FULLDATE="$STARTBIT$TODAY"
REGEX="s/date:\s.*\n/$FULLDATE/"
echo $REGEX # to make sure I'm getting what I think I'm getting
sed -e $REGEX < test.md > output.md
但我得到以下 output:
s/date:\s.*\n/date: December 29, 2021/
sed: 1: "s/date:\s.*\n/date:
": unescaped newline inside substitute pattern
所以這有點令人困惑,第一行是我的回顯模式,我在命令行上絕對看不到任何換行符。 我也不確定換行符應該在哪里?
所以然后我想,好吧,也許換行符被附加到變量之一的末尾,並且由於某種原因,當我回應它時,由於一些 bash 愚蠢,它變得不可見。 因此,基於此之前的 SO 答案,我只是進入並從所有內容的末尾刪除換行符以確保。 即:
#!/bin/bash
TODAY=$(date +'%B %d, %Y')
STARTBIT="date: "
CLEANSTARTBIT=${STARTBIT%%[[:space:]]}
CLEANTODAY=${TODAY%%[[:space:]]}
FULLDATE="$STARTBIT$TODAY"
CLEANFULLDATE=${FULLDATE%%[[:space:]]}
REGEX="s/date:\s.*\n/$CLEANFULLDATE/"
CLEANREGEX=${REGEX%%[[:space:]]}
echo $CLEANREGEX
sed -e $CLEANREGEX < test.md > output.md
我仍然得到完全相同的 output。 但現在我真的很難過。 這里不可能有換行符潛入...
幫助??
獎金可能的問題:
我使用的是 macOS 附帶的 sed 版本。 天知道是什么版本。 也許我應該嘗試使用 GNU sed?
我真的不知道正則表達式 sed 使用什么風格,或者實際上 sed 是如何工作的......我基本上只是從我在 Z23EEEB4347BDD26BFC6B7EE9A3B755 腳本中使用的正則表達式復制過來,因為永遠,我厭倦了調用 python 來進行我一直在做的這一點基本文本處理。 哈,但我實際上知道 python 正則表達式......
使用TODAY
變量
$ TODAY=$(date +'%B %d, %Y')
然后,您可以使用sed
將日期部分替換為當前日期
$ sed "s/\(date:\).*/\1 $TODAY/" test.md
---
title: I am a file
date: December 29, 2021
---
Loren ipsum blah blah blah
第一個問題:您需要雙引號引用您的變量引用(例如echo "$REGEX"
而不是echo $REGEX
)。 如果沒有雙引號,變量的值將被拆分為“單詞”,並且任何看起來像文件名通配符的單詞都將擴展為匹配文件的列表。 您幾乎從不希望這些事情發生,因此您應該幾乎總是用雙引號引用變量引用。 特別是,這個命令:
sed -e $REGEX < test.md > output.md
擴展為:
sed -e s/date:\s.*\n/date: December 29, 2021/
...和“ s/date:\s.*\n/date:
”、“ December
”、“ 29,
”和“ 2021/
”都被視為完全獨立的 arguments 到sed
。 錯誤信息具有誤導性; 真正的錯誤是第一個是不完整的sed
命令。
第二個問題是,正如您所猜測的,您的正則表達式使用了錯誤的語法方言。 macOS 自帶的版本不支持\s
簡寫,所以使用[[:space:]]
代替。 此外,使用\n
匹配行尾在sed
的任何風格中都是無效的; 改用$
(但您需要轉義它,因為它在雙引號中並且您不希望它啟動一些擴展規則):
REGEX="s/date:[[:space:]].*\$/$FULLDATE/"
從技術上講,您也不需要$
。 正則表達式匹配是貪心的,所以如果它可以匹配到行尾——它可以——它會匹配到行尾。
但最好在模式的開頭添加^
,將其錨定到一行的開頭。 否則,它將匹配一行中的任何地方的“日期:”。
第三,我建議切換到小寫或混合大小寫的變量名。 有一堆全大寫的名字有特殊含義,如果你不小心使用了其中一個,它可能會產生奇怪的效果。
最后說明:使用shellcheck.net——它會指出很多常見的腳本錯誤(例如未能雙引號)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.