Q: これMacで動かないんだけど?
A: brew install coreutils
しろ
みたいな身も蓋もないissueをよく見かける。
PerlならMacにもLinuxにも普段入っているので、これをPerlでなんとかしてみたい。
base64
base64
の-wオプションで末尾の改行を無くしたい。
#!/bin/bash
if [ $(uname) == "Darwin" ]; then
datecmd=gdate
base64cmd=gbase64
else
datecmd=date
base64cmd=base64
fi
ts=$(($(${datecmd} +%s%N)/100000))
# [...]
tmp_CWLogB64=$(echo ${tmp_CWLogRaw/__timestamp__/$ts} | gzip | ${base64cmd} -w0)
Time::HiRes
で1秒未満の現在時刻を、base64にはMIME::Base64
を使う。
ts=$(perl -MTime::HiRes=time -e 'printf "%.4f\n", time' | tr -d '.')
tmp_CWLogB64=$(echo ${tmp_CWLogRaw/__timestamp__/$ts} | gzip \
| perl -MMIME::Base64 -0777 -ne 'print encode_base64($_, "");')
cut
BSDの cut
に-zオプションが無い。
p () {
local open
open=open # on OSX, "open" opens a pdf in preview
ag -U -g ".pdf$" \
| fast-p \
| fzf --read0 --reverse -e -d $'\t' \
--preview-window down:80% --preview '
v=$(echo {q} | gtr " " "|");
echo -e {1}"\n"{2} | ggrep -E "^|$v" -i --color=always;
' \
| gcut -z -f 1 -d $'\t' | gtr -d '\n' | gxargs -r --null $open > /dev/null 2> /dev/null
}
gプレフィックスのついているものの置き換えをそれぞれ検討する:
p () {
local open
open=open # on OSX, "open" opens a pdf in preview
ag -U -g ".pdf$" \
| fast-p \
| fzf --read0 --reverse -e -d $'\t' \
--preview-window down:80% --preview '
v=$(echo {q} | tr " " "|");
printf "%s\n%s\n" "{1}" "{2}" | egrep "^|$v" -i --color=always;
' \
| perl -0 -l0 -F'\t' -nae 'print $F[0]' | tr -d '\n' | xargs -0 $open > /dev/null 2> /dev/null
}
うーんこれはいまいち分かりづらいかな。
head
head -n -1
ができない。
command -v ghead > /dev/null && HEAD="ghead" || HEAD="head"
...
SNAPSTOREMOVE="`listsnaps \"${TEMPLATE}\" \"${DATASET}\" | $HEAD -n -1`"
最後の行だけスキップ:
SNAPSTOREMOVE="`listsnaps \"${TEMPLATE}\" \"${DATASET}\" | perl -nle 'print if !eof'`"
hostname
hostnameの-iオプション。これはもとのコードにも問題ありそう。
export S3_ENDPOINT_URL=http://$(hostname -i):9000
hostname_i=$(perl -MSys::Hostname -MSocket -le '
$ip = gethostbyname(hostname); print inet_ntoa($ip) if $ip;')
export S3_ENDPOINT_URL="http://${hostname_i}:9000"
readlink
readlinkの-f/-eオプション
if [ `uname` == Darwin ]; then
READLINK=greadlink
else
READLINK=readlink
fi
SCRIPT_FN=`$READLINK -f "$0"`
Cwd::realpathを使ってcoreutilsに依存しない可搬性のあるコードにする:
SCRIPT_FN=$(perl -MCwd=realpath -le 'print realpath shift' "$0")
これはすっきり。
realpath
realpathがPOSIXに無い。上と違って厄介なのは-m/--canonicalize-missingオプション。
node_path=$(realpath --canonicalize-missing "${2-}")
realpathが出てくるところまでトラバースして残りをディレクトリ扱いに:
node_path=$(perl -MFile::Spec::Functions=catdir,splitdir -MCwd=realpath -le '
@p = splitdir shift;
push @s, pop @p while !realpath catdir @p;
print catdir realpath(catdir @p), @s;
' "${2-}")
sed
gsed "1iID\t${gene}" ${file}ID_CpG > ${file}ID_CpG_labelled
ファイルにヘッダをつけようとしたもの。BSDのsed
にi
コマンドがないので失敗してるパターン。
エスケープが甘いのでそれも考慮する。
perl -plse 'print "ID\t$gene" if $. == 1;' -- -gene="$gene" "${file}ID_CpG" > "${file}ID_CpG_labelled"
でもこんなことをするぐらいなら普通にcatしたほうがいいと思うけど。
( printf "ID\t%s\n" "$gene"; cat "${file}ID_CpG"; ) > "${file}ID_CpG_labelled"
sha512sum
@check("SHA512 checksum is correct")
def check_sha512(state: State) -> R:
return _check_sh(f"sha512sum -c {state.sha512_path}", workdir=state.release_dir)
COREモジュールの Digest::SHA
が shasum
コマンドを同梱しているので単純に置き換える:
@check("SHA512 checksum is correct")
def check_sha512(state: State) -> R:
return _check_sh(f"shasum -c {state.sha512_path}", workdir=state.release_dir)
shuf
ファイルからランダムに1行だけピックしたい。
shuf -n 1 commit_messages.txt
これはperlfaq5にある通りですね。
perl -e 'srand; rand($.) < 1 && ($line = $_) while <>; print $line;' commit_messages.txt
1行だけじゃなくて複数行(N=5)とかになると若干面倒:
perl -e '
$N = 5;
srand;
while (<>) {
if ($. <= $N) { push @l, $_; next; }
$r = rand $.; if ($r < $N) { $l[$r] = $_; }
}
print @l;
' commit_messages.txt
stat
stat
の-cオプションが無いとのこと。lsで代替するパッチが入ってるけど、lsも環境異存だし。
docker run -it -v $(pwd):/src:z --user="$(stat -c "%u:%g" .)" "$IMAGE" \
/src/script/fullbuild "$BOOTLOADER_COMMIT" "$FIRMWARE_COMMIT"
これを直接perlでやるとこんな感じ
docker run -it -v "$(pwd):/src:z" \
--user="$(perl -le 'print join ":", (stat(shift))[4..5]' .)" "$IMAGE" \
/src/script/fullbuild "$BOOTLOADER_COMMIT" "$FIRMWARE_COMMIT"
もしくは File::stat
:
UID_GID=$(perl -MFile::stat=:FIELDS -le \
'stat shift; print join "$st_uid:$st_gid";' .)
docker run -it -v "$(pwd):/src:z" --user="$UID_GID" "$IMAGE" \
/src/script/fullbuild "$BOOTLOADER_COMMIT" "$FIRMWARE_COMMIT"
timeout
timeout 2 $fmt_running_cmd &> /dev/null
ちょうどいいのがSOにあった
perl -e 'alarm shift; exec @ARGV' 2 $fmt_running_cmd &> /dev/null
他にもありそう。