使用标准工具动态计算字符串替换

使用标准工具动态计算字符串替换

是否有一种 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 '…'

相关内容