所以,我有一个简单的嵌套循环,其中外部for
循环遍历目录中的所有文件,内部for
循环遍历这些文件名的所有字符。
#!/bin/bash
if [ $# -lt 1 ]
then
echo "Please provide an argument"
exit
fi
for file in `ls $1`
do
for ch in $file
do
echo $ch
done
done
Run Code Online (Sandbox Code Playgroud)
上面的脚本不起作用。内部循环不会遍历文件名中的所有字符,而是遍历整个内容。
更新:
根据@ilkkachu 的回答,我想出了以下脚本,并且按预期工作。但是我很好奇我们可以不使用for...in
循环来迭代字符串吗?
#!/bin/bash
if [ $# -lt 1 ]
then
echo "Please provide an argument"
exit
fi
for file in `ls $1`; do
for ((i=0; i<${#file}; i++)); do
printf "%q\n" "${file:i:1}"
done
done
Run Code Online (Sandbox Code Playgroud)
由于您使用的是 Bash:
#!/bin/bash
word=foobar
for ((i=0; i < ${#word}; i++)); do
printf "char: %q\n" "${word:i:1}"
done
Run Code Online (Sandbox Code Playgroud)
${var:p:k}
给出从位置p开始的k 个字符,是内容的长度。以明确的格式打印输出,例如换行符显示为.var
${#var}
var
printf %q
$'\n'
当字符串大于几百个字符时(是的,文件名不太可能),在字符串长度上使用 for 循环并在索引处提取字符i
变得非常慢。
此答案使用高级 bash 技术:
while IFS= read -r -d "" -n 1 char; do
# do something with char, like adding it to an array
chars+=( "$char" )
done < <(printf '%s' "$string")
# inspect the array
declare -p chars
Run Code Online (Sandbox Code Playgroud)
它使用进程替换将字符串重定向到 while-read 循环中。我printf
用来避免在字符串末尾添加换行符。使用进程替换代替printf ... | while read ...
循环的主要优点是循环在当前shell 中执行,而不是在子shell 中执行。
我曾经对缓慢的程度感到好奇并对其进行了基准测试。
为了完整起见,即使问题被标记为bash,一个仅使用 POSIX shell 功能的替代方法:
#!/bin/sh
for fname
do
while [ "${#fname}" -ge 1 ]
do
rest=${fname#?} char=${fname%"$rest"} fname=$rest
printf '%s\n' "$char" # Do something with the current character
done
done
Run Code Online (Sandbox Code Playgroud)
内循环的作用:
设置rest
为fname
减去其第一个字符的值;
分配rest
从末尾删除获得的单个字符fname
to char
;
设置fname
为值rest
并重复,直到处理完所有字符。
请注意 , 中的引号${fname%"$rest"}
,以防止将$rest
的扩展用作模式。
顺便说一句,for file in `ls $1`
应该避免。最明显的原因是,如果文件名包含任何碰巧在IFS
. 更多关于这方面的信息在Bash Pitfall n。1,包括你应该做什么。
归档时间: |
|
查看次数: |
1307 次 |
最近记录: |