Is there a UNIX mechanism for replacing matched strings dynamically--with a function of the matched string?
E.g., say I want to replace URL matches with their URL-encoded counterparts or a convert certain matches from snake_case to camelCase, or just upper-case them?
Ruby has gsub
method that takes a lambda ("a block" in ruby parlance), but I'd rather not use ruby.
I tried with standard tools and FIFO, but I keep losing white space around my matches somewhere in the read
part (see below). Any guesses?
#!/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"
while IFS= read -r o
... doIFS= read -r o
... but a better approach is to setIFS
in the script so you don't have to loop over the assignment. it is better still not to useread
, but to coagulate the data in more capable reader utility and.
dot what you want (as.
will typically pull data in 4k blocks rather than byte by byte). - and this is problematic:eval "exec {"$__name"}<>"'$__tmpd/p'
– mikeserv Jan 01 '16 at 17:42s///
can be an arbitrary expression when thee
flag is used. E.g. to uppercase:perl -pe 's/(pattern)/ uc $1 /ge' file
– glenn jackman Jan 01 '16 at 22:04