2016-11-22 65 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秒更好。执行时间。 –