实现多行文本前置空格对齐裁剪的print函数
实现多行文本前置空格对齐裁剪的print函数
问题描述
我在编写相对复杂的函数时,需要用空格来排版代码。期望实现这样的逻辑:
- 先找到第一个包含非空格字符的行,统计该行开头的空格数N
- 然后把所有后续行开头的N个空格都裁剪掉
预期效果
不管输入的多行文本在什么缩进层级下,输出都要统一去掉所有行对应的前置空格,比如大多数测试用例最终都应该输出:
this is line one
this is line two
this is line three
新增测试用例的预期输出:
this
this is line two
this is line three
测试用例
以下是几个典型的测试场景:
场景1:直接调用print
print ' this is line one this is line two this is line three '
场景2:嵌套函数中的print调用
tmp() { tmp2() { print ' this is line one this is line two this is line three ' } tmp2 } tmp
场景3:首行无后续文本的嵌套调用
tmp() { tmp2() { print ' this this is line two this is line three ' } tmp2 } tmp
现有错误实现
我自己写的代码无法正确实现需求,代码如下:
print() { INPUT_STRING=$1 # 尝试统计前置空格数,但逻辑错误 COUNT_SPACES_BEFORE_TEXT=$(printf '%s' "${INPUT_STRING}" | grep -o '[^\n]*' | wc -l) # 生成对应长度的空格字符串 STRING_SPACES=$(printf "%${COUNT_SPACES_BEFORE_TEXT}s" |tr " " " ") # 构造sed命令 EXPR_SED='1d;$d;' EXPR_SED+="s/^${STRING_SPACES}//g" printf '%s' "${INPUT_STRING}" | sed "${EXPR_SED}" }
正确解决方案
核心思路是先从输入文本中提取第一个非空行的前置空格数,再用这个空格数去统一裁剪所有行的开头空格,同时保留空行原样。
修改后的print函数如下:
print() { local input="$1" # 提取第一个非空行,避免被前后空行干扰 local first_non_empty_line first_non_empty_line=$(printf '%s' "$input" | grep -m1 -v '^$') if [[ -z "$first_non_empty_line" ]]; then # 如果输入全是空行,直接输出 printf '%s' "$input" return fi # 统计该行的前置空格数:替换掉第一个非空格字符及后续内容,剩下的就是前置空格,再统计长度 local indent_len indent_len=$(printf '%s' "$first_non_empty_line" | sed 's/[^ ].*//' | wc -c) # wc -c会包含换行符,所以减去1修正长度 ((indent_len--)) # 用sed处理所有行:去掉首尾空行、保留空行、裁剪非空行的前置空格 printf '%s' "$input" | sed -E " 1d;$d; /^$/b; s/^ {0,$indent_len}// " }
代码说明
- 先定位输入中的第一个非空行,避免被输入字符串前后的空行干扰统计
- 精准计算前置空格长度:通过sed剥离非空格内容,再统计剩余空格的实际长度
- 灵活处理每行:跳过空行、裁剪非空行对应数量的前置空格,同时去掉输入首尾的空行(匹配你输入字符串的格式)
测试所有场景后,这个函数都能输出符合预期的结果。
备注:内容来源于stack exchange,提问作者Avraam
相关产品推荐
相关产品推荐

