Shell-Script

如何在 sh -c 中執行循環

  • July 12, 2022

我無法理解使用sh -c.

比方說,我想執行 for 循環for i in {1..4}; do echo $i; done。就其本身而言,這很好用。如果我將它傳遞給eval,我需要轉義$: eval "for i in {1..4}; do echo \$i; done"。但我不能使它適用於sh -c "[...]"

$ sh -c "for i in {1..4}; do echo $i; done"
4

$ sh -c "for i in {1..4}; do echo \$i; done"
{1..4}

$ sh -c "for i in \{1..4\}; do echo \$i; done"
{1..4}

$ sh -c "for i in \{1..4\}\; do echo \$i\; done"
sh: 1: Syntax error: end of file unexpected

我在哪裡可以找到有關此的更多資訊?

通常的智慧是-c在單引號內定義腳本(在 之後)。您需要使用的另一部分是{1..4}構造有效的外殼:

$ bash -c 'for i in {1..4}; do echo $i; done'  # also work with ksh and zsh

讓它與破折號(你的sh)一起工作的一種替代方法是在你正在使用的 shell 上進行擴展(我假設你使用 bash 或 zsh 作為你的互動式 shell):

$ dash -c 'for i do echo $i; done' mysh {1..4}
1
2
3
4

{1..4}是一個 zsh 運算符,從csh{x,y}大括號擴展運算符擴展而來,現在由其他一些 shell 支持,但它不是 POSIX sh 運算符(直到最近,POSIX 實際上需要 echo {1..4}輸出事件{1..4})。

即使在 zsh 或其他現在支持{x..y}的 shell 中,它也不是執行循環增加整數變數的最佳方式,因為您最終分配了所有值的列表(此處僅適用於 4,但不能很好地擴展)。for i in $(seq 4)seq不是標準命令)除了依賴$IFS.

在 ksh93、bash、zsh 中,使用:

for (( i = 1; i <= 4; i++ )); do
 printf '%s\n' "$i"
done

一般認為比較好。它還允許負值,並更好地控制索引的遞增方式。

{x..y}方法的優點是允許在多個範圍內循環,或在字母上循環,或使用填充(儘管根據外殼及其版本而有所不同):

for i in {1..5} {9..12} x{0..3} {f..p} {001..0010}; do
 ...
done

zsh中,另見:

i=; repeat 4 printf '%s\n' $((++i))

在 POSIXsh中,你會這樣做:

i=1; while [ "$i" -le 4 ]; do
 printf '%s\n' "$i"
 i=$(( i + 1 ))
done

或者:

sh -c '
 i=1; while [ "$i" -le 4 ]; do
   printf "%s\n" "$i"
   i=$(( i + 1 ))
 done'

如果您需要一個新的sh呼叫,請從另一個 Bourne/rc/fish 之類的 shell 中執行該循環。

當然,在這裡,你也可以這樣做:

for i in 1 2 3 4; do
 printf '%s\n' "$i"
done

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