天天看點

macOS:sed -i報錯:sed: 1: “xxxxx“: extra characters at the end of p command

如下,執行

sed

對檔案中的字元串進行替換,在Linux下是一點問題沒有的。

sed -i "s/find/replace/g" file.txt           

複制

但是在macOS下卻報錯了

sed: 1: “file.txt”: extra characters at the end of p command

在stackoverflow上找到這個文章《sed command with -i option (in-place editing) works fine on Ubuntu but not Mac》1,總算知道了原因:macOS與linux還是有差異的,這個問題就是macOS與linux之間差異造成的。

簡言之,就是BSD/macOS 的sed和linux(GNU)下的sed 對于

-i

參數的處理有微小的差異。

-i

即inplace,即對檔案原地修改,

-i

後面可以指定一個字尾,比如(mscOS)

-i .bak

,或在linux下

-i.bak

即修改原檔案并儲存一個字尾為

.bak

的修改前的備份

如下是Linux下

sed -i

參數說明

-i[SUFFIX], --in-place[=SUFFIX]

              edit files in place (makes backup if SUFFIX supplied)           

複制

如下是macOS下

sed -i

參數說明

-I extension
             Edit files in-place, saving backups with the specified extension.
             If a zero-length extension is given, no backup will be saved.  It
             is not recommended to give a zero-length extension when in-place
             editing files, as you risk corruption or partial content in situ-
             ations where disk space is exhausted, etc.

             Note that in-place editing with -I still takes place in a single
             continuous line address space covering all files, although each
             file preserves its individuality instead of forming one output
             stream.  The line counter is never reset between files, address
             ranges can span file boundaries, and the ``$'' address matches
             only the last line of the last file.  (See Sed Addresses.)  That
             can lead to unexpected results in many cases of in-place editing,
             where using -i is desired.

     -i extension
             Edit files in-place similarly to -I, but treat each file indepen-
             dently from other files.  In particular, line numbers in each
             file start at 1, the ``$'' address matches the last line of the
             current file, and address ranges are limited to the current file.
             (See Sed Addresses.)  The net result is as though each file were
             edited by a separate sed instance.           

複制

上面的說明可以看出差別Linux下

-i

參數後面的

[SUFFIX]

是可選的(且與

-i

之間沒有空格),如果不指定就不會備份

而macOS下

-i

參數後面的

extension

(擴充名,字尾)是必填參數(且與-i之間要有空格隔開),如果不想指定備份檔案怎麼辦?必須跟一個空字元串,也就是

-i ""

是以回到前面的那個例子,在macOS下就應該這麼寫

sed -i "" "s/find/replace/g" file.txt           

複制

如果你的腳本中很多地方都要用到

sed -i

原地修改,而又希望在Linux和macOS下都能正常使用,推薦如下方式做一個替換:

# 定義sed -i 參數(數組)
# Default case for Linux sed, just use "-i"
sedi=(-i)
case "$(uname)" in
  # For macOS, use two parameters
  Darwin*) sedi=(-i "")
esac	

########

sed "${sedi[@]}" "s/find/replace/g" file.txt           

複制

如果你還是希望使用GNU sed 文法,可以參考下面的解決辦法安裝

gsed

macOS:sed -i報錯:sed: 1: “xxxxx“: extra characters at the end of p command

參考資料

  1. 《sed command with -i option (in-place editing) works fine on Ubuntu but not Mac [duplicate]》 ↩︎