Bourne Shell中实现含空格文件名空格转义的替代方案咨询
解决Bourne Shell中替换文件名空格为转义字符的问题
因为传统Bourne Shell不支持Bash风格的参数扩展替换,所以我们需要用纯POSIX兼容的方法来实现这个需求。下面提供两种可靠的方案:
方案1:逐个字符遍历处理(纯Bourne Shell,仅依赖基础工具)
这种方法通过遍历字符串的每个字符,判断是否为空格,若是则添加转义符,否则直接拼接字符。代码如下:
ITEM="file with spaces" WRAPPED_ITEM="" # 获取字符串总长度 LEN=$(expr length "$ITEM") # 遍历每个字符(expr substr从1开始计数) for i in $(seq 1 $LEN); do # 提取当前位置的单个字符 CHAR=$(expr substr "$ITEM" $i 1) if [ "$CHAR" = " " ]; then # 双反斜杠确保最终保留一个转义符 WRAPPED_ITEM="$WRAPPED_ITEM\\ " else WRAPPED_ITEM="$WRAPPED_ITEM$CHAR" fi done # 验证结果 echo "$WRAPPED_ITEM" # 输出:file\ with\ spaces
说明:
expr length "$ITEM"是POSIX标准支持的字符串长度获取方式,可移植性强。seq 1 $LEN生成字符位置序列,配合expr substr逐个提取字符。- 用
\\拼接转义空格,因为Bourne Shell双引号内单个反斜杠会被解析为转义符,双反斜杠才能最终保留一个反斜杠。
方案2:循环使用expr批量替换空格
这种方法利用expr的模式匹配功能,反复替换字符串中的第一个未转义空格,直到所有空格处理完成:
ITEM="file with spaces" WRAPPED_ITEM="$ITEM" # 循环替换直到无空格可处理 while true; do # 优先匹配"非反斜杠结尾部分+空格+剩余部分",避免重复转义已处理的空格 NEW_ITEM=$(expr "$WRAPPED_ITEM" : '\(.*[^\\]\) \(.*\)' 2>/dev/null) # 若空格在开头,匹配兜底模式 if [ -z "$NEW_ITEM" ]; then NEW_ITEM=$(expr "$WRAPPED_ITEM" : '\(.*\) \(.*\)' 2>/dev/null) fi # 无替换发生则退出循环 if [ "$NEW_ITEM" = "$WRAPPED_ITEM" ] || [ -z "$NEW_ITEM" ]; then break fi WRAPPED_ITEM="$NEW_ITEM" done echo "$WRAPPED_ITEM" # 输出:file\ with\ spaces
说明:
expr的:操作符支持POSIX标准的模式匹配,第一个模式专门避开已转义的空格,防止重复处理。- 循环终止条件是替换前后字符串无变化,确保所有空格都被转义。
为什么你的原始方法不生效?
你尝试的${ITEM/ /$PATTERN} 是Bash/Ksh专属的扩展参数语法,传统Bourne Shell(如System V的sh)并不支持这种替换功能。该语法属于POSIX标准之外的扩展,所以在追求可移植性的纯Bourne Shell环境中无法使用。
内容的提问来源于stack exchange,提问作者confused
相关产品推荐
相关产品推荐

