Ksh

Shell 參數擴展在 AIX 中不起作用

  • March 26, 2021

我正在嘗試替換在 AIX 中不起作用的特定字元串,但是當我在 RHEL 上執行它時,我能夠獲得預期的輸出。

這是命令:

filename=25_032021_abcdefghijklmn.txt; mv /u/foo/test/25_032021_test_${filename:10:14}.txt /u/foo/test/25_032021_test_${filename:10:14}.txt.tmpExtension

這是我在 AIX 上執行此命令時遇到的錯誤

ksh: /u/foo/test/25_032021_test_${filename:10:14}.txt: 0403-011 The specified substitution is not valid for this command.

知道我可能做錯了什麼嗎?

${param:offset:length}ksh93¹ 介紹,它在ksh88. 所以你需要確保腳本是由 ksh93 而不是 ksh88 解釋的。

還要記住,至少在列表上下文中,必須在大多數類似 Bourne 的 shell 中引用參數擴展。

您可以在啟用了行編輯器的互動中鍵入Esc, Ctrl+ (在或之後)以檢查其版本。V``ksh``set -o emacs``vi``gmacs

在這裡,${filename:10:14}您可以使用

filename=25_032021_abcdefghijklmn.txt
id="${filename%.*}" # remove extension from the end
id="${id#*_*_}"     # remove up to second _ from the start
mv "/u/foo/test/25_032021_test_$id.txt" \
  "/u/foo/test/25_032021_test_$id.txt.tmpExtension"

要從開頭刪除 10 個字元而不是*_*_,請使用${param#??????????}。因此,id=${filename:10:14}假設filename至少有 24 個字元的等價物是:

id=${filename#??????????}       # remove 10 characters from the start
id=${id%"${id#??????????????}"} # remove from the end: $id stripped of
                               # its first 14 characters

這些${param#pattern}${param%pattern}是在早期版本中引入的ksh(在 ksh85 中已經存在),甚至由 POSIX 指定用於sh,因此您應該在任何時候shksh這些日子裡找到它們。

或者您可以從前 ksh 時代走古老的道路並訴諸expr²。

id=`expr "x$filename" : 'x.\{10\}\(.\{14\}\)'`

或者:

id=`expr "x$filename" : 'x.\{10\}\(.\{0,14\}\)'`

${filename:10:14}(當$filename字元少於 24 個時,更嚴格地等同於 ksh93 )。

請注意expr,如果它輸出的是數字 0 或空字元串的表示或正則表達式不匹配,則會返回失敗退出狀態,因此|| true如果您啟用了該errexit選項,您可能需要附加 a,所以它不會導致 shell 退出123456789_00000000000000.txt例如呼叫的文件。

如果id以換行符結尾(這將被命令替換剝離),該expr方法也將無法正常工作。


¹bash自 2.0(1996 年末)、mkshR30(2007 年)和zsh4.3.11(2010 年末)起也可使用,但自 1991 年的 2.0 起zsh就有。$param[first,last]

² 雖然\{n,m\}regexp 運算符在今天是標準的,但在 ksh 之前的那些日子裡它是不可用的,你不得不.\{10\}..........例如替換。

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