簡體   English   中英

使用 sed 替換 bash 腳本中的日期:幻像換行錯誤

[英]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。 但現在我真的很難過。 這里不可能有換行符潛入...

幫助??

獎金可能的問題:

  1. 我使用的是 macOS 附帶的 sed 版本。 天知道是什么版本。 也許我應該嘗試使用 GNU sed?

  2. 我真的不知道正則表達式 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM