文字列に一致する関数を使用して一致する文字列を動的に置き換える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 '…'