문자열과 일치하는 함수를 사용하여 일치하는 문자열을 동적으로 바꾸는 UNIX 메커니즘이 있습니까?
예를 들어, URL 일치 항목을 URL 인코딩된 항목으로 바꾸거나 특정 일치 항목을 Snake_case에서 CamelCase로 변환하거나 대문자로 표시하려고 한다고 가정해 보겠습니다.
Ruby에는 gsub
람다(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
동적 컴퓨터 문자열 교체를 위한 표준 도구는 셸 자체와왕. 표준 sh에는 몇 가지 문자열 조작 구성이 있고 bash에는 일반적으로 소량의 데이터에 대해 충분히 간단한 작업을 수행할 때 더 많은 구성이 사용됩니다. AWK 자체는 고전적인 명령형 구조(변수 할당, 문자열 배열, 문자열에서 문자열로의 매핑, if 문, while 루프 등)와 문자열 조작 프리미티브(연결, 분할, 정규식 일치 및 교체)를 갖춘 Turing-complete 언어입니다. 그러나 일치 그룹은 없음), ...). (튜링이 완료되었지만 간단한 정규식 대체를 넘어서면 매우 복잡해지는 sed도 있습니다.)
공백이 손실되는 주된 이유는 다음과 같습니다.변수 확장을 인용하는 것을 잊었습니다.. 또한 이를 사용할 때 주의해야 합니다 read
. 해당 작업은 행을 필드로 분할하는 것이므로 행을 그대로 읽으려면 다음이 필요합니다.IFS= read -r
.
귀하의 스크립트를 완전히 검토하지는 않았습니다. 매우 복잡해 보입니다. 그러나 공백을 보존하려면 공백을 while IFS= read -r o
대신해야 할 수도 있습니다. while read o
그러나 출력을 사후 처리하려면 다음 df
과 같은 것을 사용해야 합니다.
df -P | awk '…'