入力と同じ長さのランダム文字列を生成して、固定長テキストファイルの電子メールアドレスを表示したいと思います。 sedで文字列を逆参照として渡しています。
簡単にするために、このスクリプト(一時)は次のとおりです。
#!/bin/zsh
IFS=$'\n' # make newlines the only separator
set -f # disable globbing
#show me the input from the command line
echo $1 ${#1}
function randString() {
# just echo for demonstration
echo $1 ${#1}
# this is the bit I really want:
# cat /dev/urandom | LC_ALL=C tr -cd "[a-z]" | head -c${#1}
}
for line in $(cat $1); do
echo $line |
sed "s/\([a-zA-Z0-9]\{2,\}\)@\([a-zA-Z0-9]\{2,\}\)\.\([a-zA-Z0-9]\{2,\}\)/$(randString \\1)@$(randString \\2).$(randString \\3)/"
done
次のデータ(temp.txt)を使用してください。
me [email protected]
you [email protected]
次のように実行します。
./temp temp.txt
私に次のような出力を与えます。
temp.txt 8
me myemail 2@someserver 2.com 2
you youremail 2@anotherserver 2.biz 2
問題は、${#1}
どの文字列を入力しても2が返されることです。長さ$1
が正しくない正しい文字列をどのように返すことができますか${#1}
?IFS
ファイルの繰り返し設定により機能が終了しますか?
注:私はMacを使用しているので、GNU拡張はありません。
答え1
いくつかの診断ビットは何が起こっているかを示します。
この行を関数echo rand $1 ${#1} >&2
に追加すると、出力は次のようになります。randString
temp.txt 8
rand \1 2
rand \2 2
rand \3 2
me myemail 2@someserver 2.com 2
rand \1 2
rand \2 2
rand \3 2
you youremail 2@anotherserver 2.biz 2
stderr
入力をwithにエコーすることで、逆参照が表示する必要がある文字列の代わりに引数、および(長さ2)を使用して呼び出されていることが>&2
わかります。randString
\1
\2
\3
次のテストは、呼び出しの前にsed
withを追加して、echo
どの引数を受け取るかを確認することです。出力:
sed s/\([a-zA-Z0-9]\{2,\}\)@\([a-zA-Z0-9]\{2,\}\)\.\([a-zA-Z0-9]\{2,\}\)/\1 2@\2 2.\3 2/
このようにして、sed
文字列を\1 2
入力文字列の逆参照であるthatのように置き換え、その後にスペースと数字2を入力するように求められます。入力Eメールアドレスの文字列は関数でsed
はなくから来ます。echo
これは、文字列が引数として渡される前に$(...)
文字列のコマンド置換(拡張)が処理されるためです。入力文字列を関数に渡すには、シェル関数を呼び出す必要があります。しかし、おそらくこれを行う方法はありません。zsh
sed
sed
基本バージョンsed
。
編集が追加されました:デフォルトでは、メールアドレスを編集するためのクイックスクリプトzsh
:
#!/usr/bin/env zsh
setopt extendedglob
coproc cat /dev/urandom | LC_ALL=C tr -cd "[:lower:]"
getRand (){
print -r -- ${1//(#m)[[:alnum:]]/$(read -psk var;echo $var)}
}
while read line; do
print -r -- ${line/(#m)[[:alnum:]](#c2,)@[[:alnum:]](#c2,).[[:alnum:]](#c2,)/$(getRand ${MATCH})}
done < ${1:?}
答え2
#!/bin/zsh IFS=$'\n' # make newlines the only separator set -f # disable globbing
zsh -f
これはcsh -f
、ワイルドカードを無効にする代わりに(sh / kshエミュレーションを除く)set -o noglob
またはset +o glob
(またはsetopt
/を使用したバリエーションunsetopt
)読み取りをスキップするのと同じです。
set -f
引用符で囲まれていない拡張機能でワイルドカードを実行するバグのある機能を解決するために、他のBourneと同じシェルでこれを使用できます。ただし、zshglobsubst
にはこのオプションがデフォルトで無効になっているため(sh
/ksh
エミュレーションモードでない場合)、これらの欠陥はありません。
#show me the input from the command line echo $1 ${#1}
print -r -- $1 $#1
または、またはでなければならず、echo -E - $1 $#1
sを含む値またはで始まるいくつかの値ではprintf '%s\n' "$1 $#1"
正しく機能しません。$1
\
-
function randString() {
私はrandString() ...
Bourne構文またはKorn構文function randString {
のいずれかを選択しますが、その組み合わせは選択しません(しかしそれは単なる味の問題です)。
# cat /dev/urandom | LC_ALL=C tr -cd "[a-z]" | head -c${#1}
個々のファイルをリンクすることはcat
ほとんど意味がありません。
ほとんどのtr
実装では、文字tr -cd "[a-z]"
も生成されます。[
]
$ echo '[]123ab' | tr -cd '[a-z]'
[]ab
$ echo '[]123ab' | tr -cd a-z
ab
} for line in $(cat $1); do
これは、シェルでテキストが処理される方法ではありません。バラよりシェルループを使用してテキストを処理するのはなぜ悪い習慣と見なされますか?
echo $line | sed "s/\([a-zA-Z0-9]\{2,\}\)@\([a-zA-Z0-9]\{2,\}\)\.\([a-zA-Z0-9]\{2,\}\)/$(randString \\1)@$(randString \\2).$(randString \\3)/"
そこからシェルは$(...)
それを呼び出す前に拡張を行いますsed
。リテラルを引数として使用して呼び出しがrandString \\1
行われ、最終的に引数を使用して呼び出されます。randString
\1
sed
s/\([a-zA-Z0-9]\{2,\}\)@\([a-zA-Z0-9]\{2,\}\)\.\([a-zA-Z0-9]\{2,\}\)/\12@\22.\32/
また何と[a-z]
の共同を記録しなさい。一致はロケールによって異なります。
ここでは、テキスト処理ユーティリティ(ランダム文字列を生成できるユーティリティ)への呼び出しを実行する必要があります。それは次のとおりです。
#! /bin/sh -
exec perl -Tpe 's{\w{2,}@\w{2,}\.\w{2,}}{
$& =~ s/\w/chr 96 + rand(26)/ger}ge' -- "$@"
ここではasのsh
代わりに十分であり、テキスト処理を実行してランダムな文字列を生成するより簡単で効率的な方法が必要です。zsh
sh
perl
またはperl
代わりにスクリプトを書いてください:
#! /usr/bin/perl --
while (<<>>) {
s{\w{2,}@\w{2,}\.\w{2,}}{$& =~ s/\w/chr 96 + rand(26)/ger}ge;
print;
}
ここでは<<>>
代わりに使用されました<>
。このオプションは、名前付きファイルではなくプロセスの出力などの項目を渡すことができるループを-p
意味します。<>
ls|
ls
ls|
かなり危険です。このオプションを使用すると、-T
セキュリティの問題をある程度軽減して解決できます。<<>>
内部的に同様のことを行うことzsh
は可能ですが、きれいではありません。
#! /bin/zsh -
zmodload zsh/mathfunc
zmodload zsh/mapfile
set -o extendedglob
pattern='[[:alnum:]](#c2,)@[[:alnum:]](#c2,).[[:alnum:]](#c2,)'
for file do
print -rn -- ${mapfile[$file]//(#m)$~pattern/${MATCH//(#m)[[:alnum:]]/${(L)$(( [##36] rand48() * 26 + 9))}}}
done
ここで使用されます:
$mapfile[file]
ファイルの内容をロードします。- zshの独自のglob演算子は、一致のために正規表現を置き換えます。
rand48()
ここでは、10から35の間の36進数で乱数を生成し、文字をにA
出力Z
し、パラメータ拡張フラグを使用して小文字に変換しますL
。