是否有一种 UNIX 机制可以使用匹配字符串的函数动态替换匹配的字符串?
例如,假设我想用 URL 编码的对应项替换 URL 匹配,或者将某些匹配从 Snake_case 转换为 CamelCase,或者只是将它们大写?
Ruby 有gsub
一个接受 lambda(Ruby 术语中的“块”)的方法,但我不想使用 ruby。
我尝试使用标准工具和 FIFO,但我一直在该部分的某处丢失匹配项周围的空白read
(见下文)。有什么猜测吗?
#!/bin/bash
d="\f" #<=A character that's not expected in the input
swapNewlines() { tr "$d"'\n' '\n'"$d"; } #Since unix tools are line-oriented
#Sample transformation -- coloring red
export C_red="$(tput setaf 1)"
export C_normal="$(tput sgr0)"
transform(){ printf "$C_red%s\n$C_normal" "$*"; }
even() { sed -n '2~2p'; }
odd() { sed -n '1~2p'; }
#Open an anonymous FIFO and assign that FD to variable whose names comes on $1
mkchan(){
local __name="${1:-FD}" __tmpd= __ret=1
if __tmpd="`mktemp -d`" && mkfifo "$__tmpd/p" && eval "exec {"$__name"}<>"'$__tmpd/p'; then
__ret=0
fi
rm -rf "$__tmpd"
return "$__ret"
}
#No-op
df |sed 's/\<[1]*\>/'"$d"'\0'"$d"'/g' | swapNewlines | swapNewlines |tr -d "$d"
printf '%s\n' -------------------------------------------------------
mkchan fd; export fd
#Surround matches with the "$d" character and swap newlines with fd; then do line-processing
df |sed 's/\<[1]*\>/'"$d"'\0'"$d"'/g' | swapNewlines |
tee >(even >&"$fd") |
odd | while read o;
do printf "%s\n" "$o"
read e <&"$fd"
#printf '%s\n' "$e"
transform "$e"
done |
swapNewlines |tr -d "$d"
答案1
动态计算机字符串替换的标准工具是 shell 本身和大王。标准 sh 有一些字符串操作结构,bash 还有更多;您通常会在对少量数据执行足够简单的操作时使用它们。 AWK 本身就是一种图灵完备的语言,具有经典的命令式结构(变量赋值、字符串数组以及从字符串到字符串的映射、if 语句、while 循环等)和字符串操作原语(连接、拆分、正则表达式匹配和替换) (但没有比赛组),...)。 (还有 sed,它是图灵完备的,但是一旦超出了简单的正则表达式替换范围,它就会变得非常复杂。)
空白会丢失的主要原因是因为你忘记引用变量扩展。使用时还需要小心read
:它的工作是将行拆分为字段,因此如果您想逐字读取一行,您需要IFS= read -r
。
我还没有完全审查你的脚本 - 它看起来非常复杂 - 但如果你想保留空白,你可能需要while IFS= read -r o
而不是。while read o
但是,要对 的输出进行后处理df
,您应该使用类似的东西
df -P | awk '…'