シェルスクリプト総合 その30
■ このスレッドは過去ログ倉庫に格納されています
シェルスクリプトに関する総合スレッドです。 全般 ・荒しは無視しましょう。 ・丁寧な姿勢を心掛けましょう。 ・ネチケット(死語)を意識しましょう。 前スレ: シェルスクリプト総合 その29 https://mevius.5ch.net/test/read.cgi/tech/1537540487/ カッコの対応がおかしい。 サブシェルに入れる理由がないわけじゃないが、これで処理終了なら遅くなるだけ この程度でbash依存するのは無駄。長くなってるだけ >>683 じゃあbash 2.05aとそれ以前でエラーになると言っておこう ${l}${l:+,} は俺もよく使うが、ループで毎回比較処理をすることになるし、 最後に末尾処理をしたほうが、速いんじゃないかなーって 常々思ってしまう。lが二回出てくるから1行が長くなることが多いし 試してみたけどやっぱりだ。最後に末尾処理するほうが速い。 dashやkshだと2倍ぐらい差が出る。 bashやzshはこういう処理が何故か遅くて差もあまり出ないけど Ruby では、Array#join で自動的に、最後の区切り文字を削除してくれる ary = [ "a", "b" ] p ary.join( "," ) #=> "a,b" そりゃそうだ joinは配列から文字列に変換するときに 間の糊付けをしてくれるのだから 単純な join でセパレータが一文字なら定番の $ (IFS=,; echo "$*") で良いのだろうけど >>688 1行でできるから:+を使いたくなるけどね。 でも変数名が長いと見づらくなっちゃう。 余計なものをくっつけて、最後に削るのは一見無駄なことをしてるように思えるけど そっちの方が速いってはっきりしたので、これからは気兼ねなく、 :+を使わない方法を使えるようになったよ >>691 コマンド置換だと遅くなるよ。 IFS=,; echo "$*" でいいでしょ? IFSを戻したいなら戻せばいいだけだし。 それに変数に入れる場合、var="$*" だと最後の改行もちゃんと保存されるけど コマンド置換を使うと消えてしまう。 >>691 で > 単純な join でセパレータが一文字なら という話が出たので、問題。 今回は a b c を xaz,xbz,xcz にしたいから IFS=, を使わなかったわけだが それでもIFS=,を使うならばどうすればよいだろうか? 言い換えると、引き数 a b c を xaz xbz xcz にすればいいわけだが、 さてどうすればよいだろうか? そんな面倒なことをシェルスクリプトでやるのはやめる 客が7&いじゃなければ大丈夫だろ >>667 $ var=$(printf "x${1}z";shift;(($#)) && printf ',%sz' "${@/#/x}") >>694 $ (set -- "${@/#/x}";set -- "${@/%/z}";IFS=,;echo "$*") >>697 とっても無理矢理感があるなw まず引き数がないときに、xzと表示されるバグが有る。 あと後半意味がわからんw 単純に && printf ',x%sz' "$@" でいいんでないの? (($#))もいらんし >>698 なるほど。bash依存だとそれができるのか。それは盲点だった。 書いてなかったけど、POSIX準拠の場合はどうなるだろうか? >>699 shift 後の $# が 0 以上だと成功になってしまうので引数が1個の場合、 $ set -- a $ var=$(printf "x${1}z";shift&&printf ',%sz' "${@/#/x}") $ echo "$var" xaz,z となってしまう。 一応、引数は1個以上を想定して、2個以上なら (($#))&& は不要なんだけどね 引数なしでも処理するなら、もっと酷くなるw var=$((($#))&&{ printf "x${1}z";shift;(($#))&&printf ',%sz' "${@/#/x}"; }) おっと、 var=$((($#))&&{ printf "x${1}z";shift;(($#))&&printf ',x%sz' "$@"; }) だね ああprintfは引き数がない場合でも表示されるのか >>673 仮に別人だとしても同じようなことしてるぞ。 自分で模索しろとか言って解法を提示していないにもかかわらず ある程度要求を満たす解法が上がった瞬間それにケチ付けはじめてるじゃん。 もしもほんとうに「自分で模索しろ」って思ってんなら黙っときゃいい話。 わざわざ人が答えを述べてからそれに乗っかるなんてマネする必要ない。 >>700 このコマンドラインをPOSIXに準じたものにするには (愚直に言えば)単に${VAR/aaa/bbb}をprintf '%s' "$VAR" | sed -e 's/aaa/bbb/' に変えればいいだけでは? それかPOSIXの範疇で変数の置換展開を実現する方法を訊いているのか? それじゃあ多分無理だ。 まあ尤もprintf sedなんていちいち呼び出すなんてバカなマネは普通しないが。 >>705 違うでー、引き数の a b c を xaz xbz xcz にする方法を 聞いてるんだぜー このテクニックはいろいろと応用が効くのだ!キリッ! shiftを上手く使えば N番目以降の引数だけ別の処理に使うことってできるよね? あとbashの引数って10超えるとおかしくなるってマジ? >>709 嘘 ${10} を使えばいい。 (相当古いシェルは非対応だったりするらしいが) 引数をうまく扱うにはshift、 引数を高度に扱うにはevalを使う >>707 じゃあこれでどう? 態々IFS弄ったり何度も置換したりする必要はない。 printf 'x%sz ' "$@" | sed -e 's/ $/\ /' awkとか使ってtsvを別のtsvに挿入させる方法ってある? hoge.tsv a b e 1 2 5 huga.tsv c d 3 4 ↓ hoge_huga.tsv a b c d e 1 2 3 4 5 みたいな 行と列をひっくり返す transpose っていう awk script を作って、 ======== #!/usr/bin/awk -f {for(i=1;i<=NF;i++) a[NR,i]=$i} END{ for(j=1;j<=NF;j++) { str=a[1,j] for(i=2;i<=NR;i++) str=str" "a[i,j] print str } } ======== $ paste hoge.tsv huga.tsv | ./transpose | sort -k1,1 | ./transpose a b c d e 1 2 3 4 5 >>714 paste hoge.tsv huga.tsv | awk 'BEGIN{OFS="\t"}{print $1,$2,$4,$5,$3}' a b c d e 1 2 3 4 5 >>715 こっちのやりかたのほうが汎用的だし個人的には好きかな。 (´-`).。oO(列の挿入なのに何故ソートするんだろう) む。出遅れたか。気づいていたんだが書き込む時間がなかった。 >>716 と近いが、tsvなら入力をタブ文字にしたほうが良いだろう でないとスペースまで区切りとして扱われる paste hoge.tsv huga.tsv | awk -F"\t" -v OFS="\t" '{print $1,$2,$4,$5,$3}' >>718 それな。いかにも要求されてないことをやってるだろw このスレ、例を出すと、その例を"だけ"に通用するコード書くやつ多いぞ それを訂正するのに労力がかかるって言った意味わかるやろ? >>713 その答えもありだが、それはそれとして 引き数の a b c を xaz xbz xcz にするPOSIX準拠のテクニックって あまり知られてないのか? まさかこんなに出ないとは思わなかった。 同時に二つのファイルを開くやり方も分かったことだし、 ついでにシェルスクリプトだけで実現するやり方を書いておこう #!/bin/sh exec 3<./hoge.tsv exec 4<./huga.tsv IFS=$(printf '\t') until eof=1 read -r col1 col2 col3 <&3 && eof='' read -r col4 col5 <&4 && eof='' [ "$eof" ] do set -- "$col1" "$col2" "$col4" "$col5" "$col3" echo "$*" done >>720 おおおおおおありがてぇ! 区切りもタブ指定しないとyyyy-mm-dd hh-mm-ssとかがずれるよね GNU datamashってのがあんだね。 $ paste hoge.tsv huga.tsv | datamash transpose | sort | datamash transpose とか。挿入じゃなくてソートだけど。 ソートしたのは >>714 で hoge.tsv と huga.tsv の一行目の項目が辞書順に 並ぶ様に挿入する、って思ったんだよね >>720 FSのデフォルトはスペースとタブだから指定する必要ないよ なんかこのスレに書き込む質問者ってお客は神様だみたいな発想してる人多い印象がある。 多少の問題は自力で解決しろよって思うわ。 「その例"だけ"に〜」とか喚いてるけど,その「例」とやらがマズい例なのでは?とは1ミリも考えてなさそう。 いつも自分が正しい。問題の責任は他人にある。 まあスレの全員がそうじゃないけどね。極一部。 >>728 アホか、スペースとタブだからタブだけにするんやろw >>729 例っつーのはな、本題があって、それを補足するためのものなんだよ。 本題が本当にやりたいこと、 お前>>714 本題の文章「awkとか使ってtsvを別のtsvに挿入させる方法ってある?」 読んで、ソートしたいって思うか? お前は「いつも自分の解答が正しい。問題の責任は質問した他人にある。」 と考えてるんやろ? (´-`).。oO(勘違いしたって言ってるんだからもうええやん) >>694 の問題は本日24:00で締め切るでー シェルスクリプトに詳しいと思ってる人、 挑戦してみてやー >>733 スレ更新してから書き込むまでに、34秒以上かかっただけだよw しゅ‐き【主気】 ?名? そのものがいつも持っている運気。⇔客気(かっき)。〔夢渓筆談‐象数・一〕 はい、24:00締め切りでーす。 > 引き数 a b c を xaz xbz xcz にすればいいわけだが、 > さてどうすればよいだろうか? 解答 for i in "$@"; do set -- "$@" "x${i}z" shift done 別解 for i in "$@"; do set -- "$@" "x${i}z" done shift $(($# / 2)) なんか対抗するつもりはないけど俺の回答のほうが何やってるか分かりやすい気がする…。 まあトリッキーなシェルスクリプトを書くのは個人の自由だけど >>742 こんなのトリッキーのうちに入らんでしょ。 シャルスクリプト特有の書き方ってだけ POSIXの範囲ではシェルスクリプトで使える配列は パラメータ引数しか無い。その貴重な配列を使いこなせば bash依存もせずにすむよ bashでいいじゃん bash動かないようなクソ環境なんかないだろ今時 POSIX原理主義者の彼にはそんな煽りは通用しない! そのとおり。Debianがdashを使ってるのだ。どうしようもない。 >>743 うむ。トリッキーと書いたのは失敗だったな。 ちょっと勘違いを生んでしまった。 繰り返すけどあなたの解答を否定する気は全くないし,自分の解答が一番だなんて思ってないけど 引数「a b c d」を「xaz xbz xcz」に変換するにあたって 「手続き型言語としてのシェルスクリプト」を考えたときに 「引数に順次同じ変換を施して→余計なものを置換する」ほうが 「引数の仕様を利用してfor文を回す→(置き換えられた)引数として利用」 よりも単純かなぁと思っただけ。 あと(問題文に書いてないので推測するしかないが)引数自体はそのまま残したい場合もあるだろうから 引数を置き換えてしまう方法だと不本意な結果を招くかもしれないとも思った。 それこそ「引数を置き換えて新たな引数として利用したい」という要求ならばfor文とsetコマンドを使った方法が いいんだろうけども。 ところで>>713 がBash依存という話だけど sed -e 's/ $/\ ' ↑これってBashでしか使えなかったっけ? sedで何かから改行に置換する方法。 一応The Open Groupの仕様書には A line can be split by substituting a <newline> into it. The application shall escape the <newline> in the replacement by preceding it by a <backslash>. と書かれてるんだけど。 bash依存っていうのは ${test[@]} とか printf ',%sz' "${@/#/x}" のことな >>713 に関して言えば、 引き数の a b c を xaz xbz xcz にする方法を聞いてるのに 質問の答になってないねとしか言えないから >>750 うん? $ cat ./test.sh #!/bin/sh printf 'x%sz ' "$@" | sed -e 's/ $/\ /' $ ./test.sh a b c xaz xbz xcz となって要求を満してそうなんだけども,違うのかな? >>694 再掲 > 今回は a b c を xaz,xbz,xcz にしたいから IFS=, を使わなかったわけだが > それでもIFS=,を使うならばどうすればよいだろうか? > > 言い換えると、引き数 a b c を xaz xbz xcz にすればいいわけだが、 > さてどうすればよいだろうか? >>738 または>>739 でパラメータ引数$@に入ってないと IFS=,を使って xaz,xbz,xcz にすることができないだろ 問題をちゃんと読んでいれば、わかるはずのことだが $@ の中身が printable character だけなら GNU awk の SUBSEP 変数と同じ 様に IFS に '\034'(File Separator) を指定して [ $# -eq 0 ] && exit 0 IFS=$(printf '\034');set -- $(printf "x%sz${IFS}" "$@") IFS=,;echo "$*" とか 訂正 それだと "a b" のように引数にスペースが入ってるときにうまく動かない set -- a "b c" d IFS=$(printf '\034');set -- $(printf "x%sz${IFS}" "$@") IFS=,;echo "$*" とすると xaz,xb cz,xdz となるのだが、そういう事じゃなくて? >>758 うん。だから見落としてたw そうだな。あとはサブシェルを使うから遅いのと、 それよりも、zshだと $ ./test.sh a b c xaz,xbz,xcz, 最後に,がつく ぽじっくすに拘ったりぜっしゅに拘ったり急がしやっちゃなw >>760 Bashとか持ち出すとbash 2.xとか今現在どこでも使われていないバージョンのことも考えないといけなくなるぞw Solarisでさえbash 4なのにw 因みに>>738 や>>739 はset -uしてると引数が存在しない場合に古いシェルで動かない >>759 zsh だと set -- $(printf "x%sz${IFS}" "$@") 後の $# の値が 4 になるのね POSIX 的には $# == 3 になるのが正しい動作なのかね? >>752 訊きたいんだけど, 引数を完全に置き換えてしまうことについてはどう思ってる? 再掲するけど > (問題文に書いてないので推測するしかないが)引数自体はそのまま残したい場合もあるだろうから > 引数を置き換えてしまう方法だと不本意な結果を招くかもしれないとも思った。 引数自体を弄くる方法だとこういうことになるのでは……? >>752 例えば>>738 でIFS=,を使った場合ってどういう挙動になるのが理想なの? >>761 > ぽじっくすに拘ったりぜっしゅに拘ったり急がしやっちゃなw 何いってんの? POSIX互換シェルにこだわってるだけだよ。 POSIXもdashもzshもbashもワケてない POSIX互換シェルという一つのこだわりw >>763 > set -uしてると引数が存在しない場合に古いシェルで動かない 苦笑(知ってるw) 間違ってないが、具体的にどのシェルで動かないか言えるかい? >>764 > POSIX 的には $# == 3 になるのが正しい動作なのかね? めんどくさくて調べてないな。 でもzshだけではなく、今は使われてないだろう古いシェルや とあるシェルの古いバージョンでは4で、後のバージョンでは3になってたりするから おそらく $# == 3 が正しいのだろう。 だが、現実として動かないシェルがある POSIX互換シェルに拘ってるといったが、正確にはPOSIX互換シェルと名乗っている 現実に存在するシェルに拘っているというべきか ZshってPOSIX互換を謳ってたっけ? 少なくとも公式ページ[zsh.org]にはそんな記述は見当らんが…。 もしかしてemulate -R shをPOSIX準拠モードとかだと思ってる…? >>770 いやまって。マジで分からんわw 引数「a b c」を「xaz xbz xcz」にする過程でIFS=,を使う場面なんてあるか? そして仮にあったとして >>713 と>>738 とでその時の挙動に違いがあるとは思えんのだが↓ もしかして 引数「a,b,c」を「xaz xbz xcz」にするとかそういう話か? for i in IFS=, "$@"; do set -- "$@" "x${i}z" shift done echo "$@" こんな風に?w >>762 Solarisは10まで(POSIX互換ではない)Bourne Shellが デフォルトシェルだってのがいただけない Extended Supportが2021年までらしい。 まあ俺はPOSIXじゃないからという理由で切り捨てることにしてるが >>694 > 今回は a b c を xaz,xbz,xcz にしたいから IFS=, を使わなかったわけだが →分かる > それでもIFS=,を使うならばどうすればよいだろうか?→そうだな,どうすればいいんだろう。 > 言い換えると、引き数 a b c を xaz xbz xcz にすればいいわけだが、→え?空白区切り?今IFS=,の話だよな?? > さてどうすればよいだろうか? →???? >>772 >>694 再掲 読める? > 今回は a b c を xaz,xbz,xcz にしたいから IFS=, を使わなかったわけだが > それでもIFS=,を使うならばどうすればよいだろうか? >>774 お前プログラマに向いてないよw 推論能力が圧倒的に不足してる 引数が、xaz xbz xcz の状態なら、IFS使って xaz,xbz,xcz にできるだろw って言っても理解できないんだろうなw >>771 zshのマニュアルにはPOSIXという文字が50個以上存在する これでPOSIXを意識してないとか考えられんわw >>778 Zsh is able to emulate POSIX shells, but its default mode is not POSIX compatible なんて書いてあるから何か変数を設定しないとダメみたいだな 色々弄ってるけど $# が 3 にならんのぅ…ソースコード読むしかないかなw >>780 たぶんその挙動はバグで確定だと思うでw >>768 の質問には答えてくれないのかな? set -uしてると引数が存在しない場合に動かない古いシェルはなにか? >>776 うんだってプログラマじゃねーもんw 寧ろその程度の能力でイキれるお前がプログラマっぽくねぇなw こっちの類推能力も足りんかもしれんが そっちの説明能力もかなり欠如してんぞw >>782 すまんがその前に>>765 に答えてほしい ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる