2016-11-22 48 views
2
#!/bin/sh 

read -p "Enter sequence: " seq 

for char in $seq; do 
    echo "$char" 
done 

我從標準輸入讀取「字符」序列。例如讓它成爲1234(),在POSIX中對字符串中的字符進行迭代sh

我想改變它是這樣的:

'1' '2' '3' '4' '(' ')' ',' 

我不想回應這個序列。我需要它有這個新的價值。

標準sh腳本中可能嗎?

+0

嗯。在bash或ksh中有一個非常好的答案,它不涉及外部工具的開銷,但是POSIX sh要求使得這更難。 –

+0

如果用戶輸入空格會發生什麼?如果'seq =「hello world」'怎麼辦? –

+0

順便說一句,在大多數情況下,用單引號包裝不太可能是一種有用的行爲。從命令替換中讀取時,這些引號是字面的,而不是語法的,因此它們不會以任何方式阻止評估。 –

回答

1

你可以用分割字符串sed(1):

seq=`printf "%s\n" "$seq" | sed 's/./ &/g'` 
+1

'printf'%s \ n'「$ seq」'會比'echo $ seq'副作用小。如果您想要被嚇到,請在[用於'echo的POSIX規範](http://pubs.opengroup.org/onlinepubs/009695399/utilities/echo.html)中搜索「implementation-defined」在應用使用部分。此外,'echo $ seq'上缺少引號意味着你用當前目錄中的文件列表替換'*',帶空格的標籤(假設爲默認IFS)等。 –

+0

好的,謝謝你的提示。我更新了代碼。 – clemens

+0

由於命令替換會隱式刪除尾隨的換行符,因此我不太確定那裏是否有任何優勢。 –

1

我很驚訝,但是這是我所有的炮彈,並用奇怪的字符太(包括,例如,-())工作(除了:):

iterate_over_chars() 
{ 
    #reset OPTIND in case this is going to be used multiple times 
    #(doable without local (which isn't POSIX) but local is nice and very portable) 
    local seq="$1" OPTIND=1 
    while getopts "$seq" opt "-$seq"; do 
     echo "$opt" 
    done 
} 
printf '%s\n' Enter sequence 2>/dev/null 
read seq #read -p isn't exactly POSIX 
iterate_over_chars "$seq" 

的想法是與-前綴詞,然後把這個詞作爲一個選項組。

+1

我使用_sed(1)_作爲POSIX shell腳本來做到這一點,但對於調用它的性能開銷感到不滿,所以我搜索了一個純shell解決方案,當我無法在我的系統上找到一個好的解決方案時擁有。我認爲這種方法非常簡單。感謝您發佈這個答案。我真的認爲這應該是公認的解決方案,特別是最近的編輯。 –

+0

@EricPruitt感謝您的編輯。我以不同的方式整合了這個建議,因爲我想保持答案的簡短,並且我認爲subshel​​l打敗了整個事情的目的(避免了過程產生的開銷)。 – PSkocik

+0

我不會扭轉你的編輯,但我不同意subhells擊敗目的。在大多數系統中,使用子shell將導致在調用另一個_fork(2)_和_execve(2)_時調用_fork(2)_。在我正在處理的腳本中,我剛剛嘗試了在子殼體中使用getopts與使用_sed(1)_。子shell版本的1,000次調用在3.7秒內運行。這仍然比_sed(1)_版本的14.3秒更好。執行時間。 –

相關問題