[英]sed search/replace on macOS: Pass back reference to another command within the replace string
我在 macOS 上有一個包含一堆日志及其時間戳的文件。 時間戳的格式為“自紀元以來的秒數”,但我想將它們全部替換為“MM-DD-YY HH:MM:SS”格式。 例如:
自 Epoch 以來的1605726368.416115
秒應替換為11-18-20 20:06:08
。 請注意,自 Epoch 時間戳是十進制值以來的秒數,這就是日志的時間戳記。
我試圖用sed
和date
實現這一點,如下所示:
sed -E -i '' -e "s/^([0-9]+)([0-9.]+)/$(date -r \\1 '+%m-%d-%Y %X')/" logfile.txt
問題是date
將\\1
解釋為僅 1 秒,而不是引用正則表達式中的([0-9]+)
捕獲組的反向引用。 我嘗試了很多事情,比如用$1
或\\\\1
替換\\1
,搞亂單引號和雙引號,從自制軟件安裝 gnu-sed 並嘗試使用/e
標志,但沒有任何效果。 所以我的問題基本上是:是否可以在 $(...) 命令替換中使用 \\N 反向引用(特別是在 sed 替換字符串的上下文中)?
如果可能,我想避免在 while 循環中讀取每一行並在每一行上調用sed
,因為這太慢了。
您不能對sed
捕獲的值的反向引用進行命令替換,因為命令替換將在之前運行並且它將采用文字\\1
而不是實際捕獲的值。
如果您對perl
解決方案沒問題,那么這將正常工作:
perl -pe 's/^[0-9]+\.[0-9]+/{
use POSIX qw( strftime ); strftime("%m-%d-%Y %X", localtime($&));
}/e' file.log
PS:如果您的 EPOCH 值在GMT
您可以使用gmtime
而不是localtime
。
我將從兩個帶有paste
糟糕解決方案開始,這可能會讓你感到開心。
當所有行都以時間戳開頭時,您可以使用
paste -d " " <(printf '%(%m-%d-%Y %X)T\n' $(cut -d"." -f1 logfile.txt)) \
<(cut -d" " -f2- logfile.txt)
對於只有線戳的行,這將失敗,在接下來的幾年中,您可以使用
paste -d " " <(printf '%(%m-%d-%Y %X)T\n' $(cut -d"." -f1 logfile.txt)) <(cut -c19- logfile.txt)
您幾乎可以像以前一樣使用sed
。 首先提取命令,然后獲取它們。
. <(sed -E 's/^([0-9]+)([0-9.]+)(.*)/printf "%(%m-%d-%Y %X)T" "\1"; echo "\3"/' logfile.txt)
我認為awk
是最好的:
awk -F "." '{ print strftime("%m-%d-%Y %X",$1) substr($0,17) }' logfile.txt
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.