为何函数传参与管道传参结果不同?trim函数管道调用失败原因
Shell字符串去空格方案及管道调用函数的问题解析
我看到你找到了两种在Shell中去除字符串空格的方案,也遇到了管道调用自定义trim函数失败的问题,下面来详细解析:
两种去空格方案对比
1. 借助外部工具xargs
这是一种快速实现的方案,通过管道将输出传递给xargs,它会自动去除字符串的前后空格,还会压缩中间的连续空格:
# 示例:去除WiFi SSID输出的前导空格 $ /System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport -I | awk -F: '/ SSID/{print $2}' | xargs <some-ssid>
2. 自定义Shell原生trim()函数
这种方案利用Shell本身的字符串处理能力,不需要启动外部进程,效率更高,正如评论所说:
这绝对是理想方案。仅为修剪单个字符串空白就派生外部进程不合理——多数Shell含bash本身就有原生字符串处理功能。
函数代码如下:
trim() { local var="$*" # 移除前导空白字符 var="${var#"${var%%[![:space:]]*}"}" # 移除尾随空白字符 var="${var%"${var##*[![:space:]]}"}" echo -n "$var" }
管道调用失败的原因解析
你遇到的问题是:直接传参给trim能正常工作,但通过管道调用时却没有输出,核心原因在于函数的输入处理逻辑:
- 当你执行
trim "$wifi"时,"$*"会把传入的位置参数(这里就是$wifi)拼接成字符串,函数能正常获取到需要处理的内容,自然可以输出修剪后的结果。 - 而当通过管道调用
trim时,函数的输入是来自标准输入(stdin),但原trim()函数并没有读取标准输入的逻辑——它只处理位置参数$*,此时位置参数为空,所以函数内部的var是空字符串,最终没有输出。
修复trim()函数使其支持管道输入
要让函数同时支持传参和管道输入,我们可以修改函数,让它优先处理位置参数,没有参数时再读取标准输入:
trim() { local var # 判断是否有传入位置参数 if [ $# -gt 0 ]; then var="$1" # 用$1替代$*,更精准处理单个字符串 else var=$(cat -) # 读取标准输入的内容 fi # 移除前导空白字符 var="${var#"${var%%[![:space:]]*}"}" # 移除尾随空白字符 var="${var%"${var##*[![:space:]]}"}" echo -n "$var" }
修改后,不管是传参还是管道调用都能正常工作了:
# 管道调用现在可以成功去除空格 $ /System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport -I | awk -F: '/ SSID/{print $2}' | trim <some-ssid> # 传参方式依然有效 $ wifi=$(/System/Library/PrivateFrameworks/Apple80211.framework/Resources/airport -I | awk -F: '/ SSID/{print $2}') $ trim "$wifi" <some-ssid>
内容的提问来源于stack exchange,提问作者ginjaemocoes
相关产品推荐
相关产品推荐

