posix sh:是否可以在不使用外部工具的情况下迭代字符串?

时间:2018-04-06 17:31:20

标签: shell sh posix

在POSIX sh中,我能够使用while循环遍历字符串中的每个字符并剪切;这是一个示范:

SELECT CountryCode, COUNT(*) 
FROM table 
WHERE CountryCode IN ('AFG','NLD','IND') 
GROUP BY CountryCode;

输出是:

#!/bin/sh

lizards='geckos,anoles'

string_length="${#lizards}"

i=1
while [ "$i" -le "$string_length" ]; do
    char="$(echo "$lizards" | cut -c "$i")"
    echo "$char"
    i="$(( i + 1 ))"
done

如果没有必须调用外部命令,我有办法吗?

3 个答案:

答案 0 :(得分:4)

您可以使用printf获取第一个字符和参数展开以将其删除:

#!/bin/sh

lizards='geckos,anoles'

while [ -n "$lizards" ]; do
    printf '%.1s\n' "$lizards"
    lizards="${lizards#?}"
done

答案 1 :(得分:1)

使用fold代替cut,您可以轻松地将外部命令的数量从每个字符一个减少到整个字符串的一个:

#!/bin/sh

lizards='geckos,anoles'

echo "$lizards" | fold -w 1

我想不出一个纯粹用内置的方法来做这件事。但我确实想到了一个丑陋的方式:

#!/bin/sh

lizards='geckos,anoles'

string_length="${#lizards}"

# Initialize j to length string_length-1 filled with ?'s and k to empty
i=1
j=
k=
while [ "$i" -lt "$string_length" ]; do
    j="?$j"
    i="$(( i + 1 ))"
done

i=0
# From here on, j contains string_length-i-1 ?'s and k contains i ?'s
while [ "$i" -lt "$string_length" ]; do
    char="${lizards#$k}"
    char="${char%$j}"
    echo "$char" # or printf '%c\n' "$char"
    j="${j#?}"
    k="?$k"
    i="$(( i + 1 ))"
done

要理解它,您必须先了解${var#pattern}${var%pattern}扩展,这些扩展会比较{{1}的开头(#)或结束(%)到模式(类似glob,而不是regexp)并删除匹配的部分。 (这些是最短的匹配,$var##进行最长的匹配,但这并不重要。)

因此,如果我希望%%删除前2个字符,我会使用$var。如果我想删除最后2个字符,请使用${var#??}。所以我做了一个循环,使用可变数量的${var%??}每次修剪两端。基本上它是这样做的:

?

我特别喜欢编写使用char=${lizards#}; char=${char%????????????}; echo $char char=${lizards#?}; char=${char%???????????}; echo $char char=${lizards#??}; char=${char%??????????}; echo $char char=${lizards#???}; char=${char%?????????}; echo $char char=${lizards#????}; char=${char%????????}; echo $char char=${lizards#?????}; char=${char%???????}; echo $char char=${lizards#??????}; char=${char%??????}; echo $char char=${lizards#???????}; char=${char%?????}; echo $char char=${lizards#????????}; char=${char%????}; echo $char char=${lizards#?????????}; char=${char%???}; echo $char char=${lizards#??????????}; char=${char%??}; echo $char char=${lizards#???????????}; char=${char%?}; echo $char char=${lizards#????????????}; char=${char%}; echo $char 构造的行j="${j#?}"来从变量中删除一个字符,该变量将用作下一个${var#pattern}构造中的模式。

实际上,我认为我会使用${var%pattern}

答案 2 :(得分:1)

从几年前开始,这里的{em> POSIX 方法与that other guy's answer类似,而printf代替${parameter%word}依赖于更多变量(太多?)并且需要删除最小的后缀模式${parameter#word})和删除最小的前缀模式splitchar(){ unset r c q="$1" while [ "$q" ]; do s="$q" q="${q#?}" c="${s%$q}" r="$r$c " done echo "${r%?}"; } )参数扩展:

splitchar hello

示例:

h
e
l
l
o

输出:

df['end_date'] = df['start_date'] + df.total_waiting_days.apply(lambda x :pd.Timedelta(x, unit='D'))
相关问题