Korn Shell中如何将用户输入日期变量传入sed命令
问题:Korn Shell中sed命令无法传入变量导致执行错误
在Korn Shell环境下,我通过accept_date.ksh脚本获取用户输入的日期并存入broken_date变量,但把这个变量传入sed命令批量修改文本文件指定位置的日期时,出现了sed: unknown command错误。原静态sed命令可以正常生效,修改后就报错了。
示例文本
126731E 0000000033220422 000003312634460-0003-1 134180D 0000000052220419 000006012622399-0003-1 134307-004K 0000000016220420 000001612635621-0003-0 141014-001B 0000000040220419 000004012632585-0003-0 134886C 0000000034220419 000007612620821-0003-1 123899B 0000000050220412 000005012635007-0003-1 121543C 0000000059220419 000007512621925-0003-1 118238C 0000000070220419 000007012632584-0003-0 121852A 0000000122220419 000013512622569-0003-1 123124A 0000000141220419 000014112631954-0003-0 123157C 0000000344220422 000034412634707-0003-1
期望结果
126731E 0000000033220422 000003312634460-0003-1 134180D 0000000052220102 000006012622399-0003-1 134307-004K 0000000016220420 000001612635621-0003-0 141014-001B 0000000040220419 000004012632585-0003-0 134886C 0000000034220102 000007612620821-0003-1 123899B 0000000050220412 000005012635007-0003-1 121543C 0000000059220102 000007512621925-0003-1 118238C 0000000070220419 000007012632584-0003-0 121852A 0000000122220102 000013512622569-0003-1 123124A 0000000141220419 000014112631954-0003-0 123157C 0000000344220422 000034412634707-0003-1
当前脚本片段
export GLOBAL_UTILS="../../utils" broken_date=`$GLOBAL_UTILS/accept_date.ksh "$title" "$message" "$btn_width" "$btn_1_txt" "$btn_2_txt"` print $broken_date sed -f [^ ]\+0\+\([1-9]\)\([0-9]\{1,3\}\)\([0-9]\{6\}\)0\+\1\?\2/!{s/[0-9]\{6\}/"$broken_date"/ ../1111003.txt > new.txt
原静态sed命令
/[^ ]* \+0\+\([1-9]\)\([0-9]\{1,3\}\)\([0-9]\{6\}\).* 0\+\1\?\2/!{ s/[0-9]\{6\} /220102 / }
报错信息
+ + echo 220909 RESULT=220909 + break + + echo 220909 + bc date_in=220909 + [ 220909 -lt 200101 ] + [ 220909 -gt 501231 ] + dlg close + break + echo 220909 broken_date=220909 print $broken_date + print 220909 220909 sed -Ee "/[^ ]* +0+([1-9])([0-9]{1,3})([0-9]{6}).* 0+\1?\2/ ! {s/[0-9]{6} /$broken_date /" -e '}' ../1111003.txt > . ./new.txt + sed -Ee /[^ ]* +0+([1-9])([0-9]{1,3})([0-9]{6}).* 0+\1?\2/ ! {s/[0-9]{6} /220909 / -e } ../1111003.txt sed: unknown command
问题根源
- sed命令语法混乱:当前脚本里的sed命令没有用引号包裹完整逻辑,导致shell解析时把sed的命令拆成了多个无效参数,比如单独的
}被当成了sed命令,引发"未知命令"错误。 - 变量引用方式错误:没有正确处理sed中变量的替换逻辑,同时原静态命令的正则转义在带变量的写法里没有适配好。
修正后的可行写法
写法1:用双引号包裹完整sed命令
sed -E "/[^ ]* +0+([1-9])([0-9]{1,3})([0-9]{6}).* 0+\1?\2/!{s/[0-9]{6} /$broken_date /}" ../1111003.txt > new.txt
- 用双引号包裹整个sed命令,shell会先替换
$broken_date变量,同时保证sed的逻辑作为一个整体被解析,不会被拆分。 - 添加
-E参数启用扩展正则表达式,这样正则里的+、{}不需要转义,和原静态命令逻辑保持一致。
写法2:用临时文件存放sed脚本(适合复杂逻辑)
如果sed的逻辑更复杂,可先把脚本写入临时文件再调用:
# 生成sed脚本临时文件 cat > sed_script.tmp << EOF /[^ ]* +0+([1-9])([0-9]{1,3})([0-9]{6}).* 0+\1?\2/!{ s/[0-9]{6} /$broken_date / } EOF # 执行sed命令 sed -E -f sed_script.tmp ../1111003.txt > new.txt # 删除临时文件 rm -f sed_script.tmp
- 通过here-document生成脚本文件,
$broken_date会被自动替换成变量值。 - sed通过
-f参数读取脚本文件执行,避免了命令行的语法混乱问题。
关键注意事项
- 必须用
-E:启用扩展正则表达式,否则需要给+、{}加转义符,容易出错。 - 引号选双引号:单引号会阻止shell替换变量,双引号既能替换变量又能保留sed命令的完整性。
- 不要拆分sed逻辑:原脚本里把
}单独作为-e参数是错误的,sed的命令块必须作为一个整体。
内容的提问来源于stack exchange,提问作者fletching
相关产品推荐
相关产品推荐

