Bash脚本用tail读取文件路径作为程序参数失效原因及解决
问题现象
脚本同目录下./config2.cfg文件通过tail读取到的最后一行内容为:
LastUsedROM = /media/user1/MIYOO/Roms/MD/Golden Axe II (World).zip
最初编写的脚本逻辑为:通过tail读取config2.cfg最后一行赋值给LASTSAVED变量,截去开头固定的LastUsedROM = 前缀后,调用mednafen并传入该路径作为参数,但脚本执行失败。初始故障脚本代码:
#!/bin/bash LASTSAVED=$( tail -n 1 ./config2.cfg ) LASTSAVED=${LASTSAVED:14} mednafen "$LASTSAVED"
存在一个反常现象:如果将目标行字符串直接硬编码赋值给LASTSAVED变量,做完全相同的字符串截取后调用mednafen,可以正常运行。硬编码测试脚本代码:
#!/bin/bash LASTSAVED="LastUsedROM = /media/user1/MIYOO/Roms/MD/Golden Axe II (World).zip" LASTSAVED=${LASTSAVED:14} mednafen "$LASTSAVED"
编写对比测试脚本后发现,两种赋值方式下echo输出的变量内容完全一致,均为/media/user1/MIYOO/Roms/MD/Golden Axe II (World).zip,肉眼无法定位两者差异。
根因分析
最终排查确认问题根源:config2.cfg文件的行尾存在picodrive模拟器生成的多余回车符(\r),这类不可见控制字符在普通echo输出时不会被打印出来,导致传入mednafen的路径末尾携带无效字符,程序无法匹配到正确的文件路径。
另外脚本最终运行设备为powkiddy v90,该设备仅提供sh环境、无Bash解释器,且设备自带的tail命令存在兼容问题,原Bash专属语法和tail调用写法在该设备上无法稳定运行。
修复代码
改用兼容性更好的sed命令读取文件最后一行,同时增加字符串处理逻辑,移除变量内的制表符、回车、换行等不可见空白字符后再传入mednafen,即可正常运行。修复后的脚本如下:
#!/bin/sh # 原tail调用写法因设备兼容问题弃用 #LASTSAVED=$(tail -n1 ./config2.cfg) LASTSAVED=$(sed '$!d' ./config2.cfg) # 截去开头固定的"LastUsedROM = "前缀 LASTSAVED=${LASTSAVED:14} # 移除所有制表符、回车、换行类不可见空白字符 LASTSAVED=${LASTSAVED//[$'\t\r\n']} mednafen "$LASTSAVED"
内容的提问来源于stack exchange,提问作者climero333
相关产品推荐
相关产品推荐

