シェルスクリプト総合 その26 [無断転載禁止]©2ch.net
■ このスレッドは過去ログ倉庫に格納されています
シェルスクリプトの総合スレです。
□お約束
・特記なき場合はBourne Shell(/bin/sh)がデフォルトです。
bash/zsh/ksh/ashなどに依存する場合は明示しましょう。
Linuxユーザは/bin/shの正体がbashまたはdashなので特に注意。
FreeBSDユーザは/bin/shの正体がashなので注意。
v7 shに一番近くて、現役のshは、OpenSolaris由来のheirloom sh。
http://src.illumos.org/source/xref/illumos-gate/usr/src/cmd/sh/
http://heirloom.sourceforge.net/sh.html
・csh/tcshのシェルスクリプトは推奨されません。
(理由は「csh-whynot」でググれ)
・UNIXにはシェルスクリプトに便利な小さなコマンドがいろいろあります。
manや参考リンクを見ましょう。
aproposないしはman -kでそれらしい単語による簡単な検索もできます。
・シェルで使えるワイルドカード等は正規表現ではありません。
正規表現の話題はスレ違い(正規表現スレへ)
・シェルスクリプトのことをシェルってゆーな
□初心者へのアドバイス:
・適した道具を判断するのも頭の重要な使い方。シェルスクリプトよりも
awkまたはperlの方が適した処理にはそちらを使いましょう。
・知らないコマンドが出てきたらmanを引きましょう。
・思い通りに動かないときは、まずは sh -x でトレースしましょう。
□回答者への注意事項:
・シェルスクリプトでの処理方法を質問しているのに、よくわからずに
「そういうのはperl使いましょう」と回答するのはやめましょう。
安易にperlに逃げずにシェルスクリプトで処理するのが頭のいいやり方。
前スレ
シェルスクリプト総合 その25
http://echo.2ch.net/test/read.cgi/unix/1439563321/ >>337
ありがとうございます!
LS_OPTIONS は知りませんでした。MANOPT や LESS みたな感じなんですかね。
函数は POSIX に合わせて ls () にしようと思ったんですが,ちょっと個人的に気持ち悪くて,どうしても function が取っ払えませんでした……。 シェルの解釈を標準出力に印刷するコマンドってある/作れますか?
グロブやエイリアスがどう解釈/引き渡されるのかを知りたいです。
$ showraw 'ls */*'
ls a/a a/b a/c b/a c/a c/b
みたいな。
検索も一通りしたのですが見付からないです。
シェルによってシェルそれ自身の機能を調べるのは無理なんですかね。 $ showraw 'ls */*'
ls -F -A a/a a/b a/c b/a c/a c/b
エイリアスも解釈されるのでこんなかんじですね。 コマンドの方はtype ls 引数の方はecho */* で良くね
取り敢えずshとbashで確認 $ ls */*
と入力したところで ESC \C-e をタイプするとエイリアスが展開され
\C-x* をタイプするとワイルトカードが展開される >>340
$ set -x
$ ls */* >/dev/null >>343 -- >>345
ありがとうございます。しかしできればエイリアスごと展開したいのです。
>>346
おわ!まさにこんな感じです。多分コマンドプロンプト関連の命令群も一緒に出力されますが,これはまあ awk か何かで頑張って切り取ります。一応 zsh,bash,dash で確認できました。 >>330
set -u 便利ですね
~/.bashrcに書こうかしら
とくに弊害ないですよね? すいません。わかるかたいたら教えてください。
基本的にカンマ区切りの行なのですが、1列目が""で囲まれ、"aaa,bbb,ccc"のように
なることがあります。
1列目のみに発生します。
この1列目のケースだけ、カンマをスペース等に置換したいと思っています。
イメージはこうです。
"aaa,bbb,ccc",AAAA,BBBB,CCCC
aaa,AAAA,DDDD,EEEE
↓
"aaa bbb ccc",AAAA,BBBB,CCCC
aaa,AAAA,DDDD,EEEE
理由はエクセルに取り込むときにずれてしまうためです。
awkで出来た気がするのですが、うまく出来ません。
どなたか心当たりないでしょうか。 Excelならダブルクオートちゃんと扱うはずだよ
勘違いか、変な文字入ってない? テキストをコピーして貼り付ける時にカンマ区切りでバラすように貼り付けると囲んでてても関係なくバラさなかったっけ? もっとうまく書けそうな気がするものの
perl -pe 'if (/^"/) { @f = split/"/, $_, 3; $f[1] =~ s/,/ /g; $_ = join "\"", @f }' awkとBEGINで昔出来た記憶があるのですが。上手くいかず。
>>350
あれ、確かにEXCELには想定ではれました、すいませんさっきも同じにようにはったつもりで、ばらされたのですが。
>>353
一行Perlの文法の意味はわかりませんが、確かに出来ました! 区切り文字を"にして配列に取り込んで,を に置換えた後、最初と最後に"を追加する
perl -F\" -anle '$F[1] =~ s/,/ /g; $F[1] =~ s/(.+)/\"$1\"/; print @F'
awkでは
awk 'BEGIN {FS="\""; OFS="\""} {gsub(","," ",$2); print $0}'
でいいような、なんか自信ないけど GNU awk の FPAT を使ってこんな感じで
gawk -vFPAT='(".+?"|[^,]*)' -vOFS=, '{gsub(/,/," ",$1);print}' data.csv perl -pe 's/^("[^"]*")/$1=~s|,| |gr/e' perl -pe 's/,(?=.*\")/ /g' >>349
#!/bin/sh
IFS=\"
while read X Y Z ; do
if [ "$X" = "" ] ; then
echo -n \"$Y\" | sed 's/,/ /g'
echo $Z
else
echo $X
fi
done sed '/^"[^"]*"/{H;s///;x;s/\n//;s/^\("[^"]*"\).*/\1/;s/,/ /g;G;s/\n//;}' bashで変数展開するときに、名前末尾にハイフン付けるのはどういう意味なんでしょうか?
${abc-} 今まさにそのページ読んでたけど、:いるよな
ナシの使い方なんてあったっけか > コロンを省略した場合には設定されているかどうかのみを調べます。 何度か読み返してようやく理解した
unsetされてるか空値が入ってるかの違いに対応出来るのか ログイン時に読み込まれる ~/.profile ファイルは,「誰が」読み込んでいるのでしょうか。
普通 sh もしくはその代替シェルかなと思うのですが,実際はどうなのか気になります。
というのも,私が普段使っている Debian GNU/Linux ではデフォルトシェルは bash に指定しているのですが,~/.profile の中に bash っぽい変数 (${HOGE} という書き方) があったので。 あぁ、すまん
>>368へのレスか
たしかに${HOGE}記法はたいていのshで使えるね >>374
何を言ってるのがわからん。bshが元祖なのに。 スレチ気味だけど,ある種の Shell って,
$ cd ///////
みたいなことをするとルートディレクトリだと認識するんだな。
個人的に ~ がすごく打ちにくい位置にあるので // を ~ だと解釈させようと試行錯誤してるときに発見した。
これはルートディレクトリが特別って訳じゃなく,
$ ls /usr////bin///////
みたいなことでも問題ない。ということは // == ~ にすることは Shell のソース弄るくらいしか方法がないということになる。
俺みたいな無駄な努力をしないために残す もしかして RFC とかで実装が統一されてんのか。 $ /bin/echo /usr////bin///////
/usr////bin///////
$
となるので、lsについてはシェルが解釈してるわけではなくlsが解釈していると思われる まあ//を~にしたいならシェルのキーバインド使えばいいんじゃないですかね ちなみにこんなんなったりする
シェルの種類によって挙動は違うかも
$ cd //
$ pwd
//
$
理由は
http://www.unixguide.net/unix/bash/E10.shtml キーバインドいじっちゃうと
「http://」を打とうとして「http:~」になったりして困らないか >>382
「An implementation may」だから必ずではないのでは ファイルをリネームしてコピーし続けるスクリプトなんですが
コマンドが見つからないと出てよくわかりません
#/bin/sh
PATH='/var/log/'
PATH2='dnsmasq.log'
DOT='.'
for i in 6 5 4 3 2 1
do
PATH3=$PATH$PATH2$DOT$i
PATH4=`expr $i - 1`
PATH5=$PATH$PATH2$DOT$PATH4
mv $PATH5 $PATH3
done
PATH6=0
mv $PATH$PATH2 $PATH$PATH2$PATH6
exit 0 >>391
for VAR in ARGS; do
command;
done sh -xで実行してみると以下の通り出力されました
+ PATH=/var/log/
+ PATH2=dnsmasq.log
+ DOT=.
+ PATH3=/var/log/dnsmasq.log.6
+ expr 6 - 1
./splitLog.sh: 1: ./splitLog.sh: expr: not found
+ PATH4=
+ PATH5=/var/log/dnsmasq.log.
+ mv /var/log/dnsmasq.log. /var/log/dnsmasq.log.6
./splitLog.sh: 12: ./splitLog.sh: mv: not found
(省略)
+ PATH3=/var/log/dnsmasq.log.1
+ expr 1 - 1
./splitLog.sh: 1: ./splitLog.sh: expr: not found
+ PATH4=
+ PATH5=/var/log/dnsmasq.log.
+ mv /var/log/dnsmasq.log. /var/log/dnsmasq.log.1
./splitLog.sh: 12: ./splitLog.sh: mv: not found
+ PATH6=0
+ mv /var/log/dnsmasq.log /var/log/dnsmasq.log0
./splitLog.sh: 17: ./splitLog.sh: mv: not found
+ exit 0 とりあえず何がしたいかを書け
そんな汚いもん見せられても何がしたいのか分かりにくい PATH潰すんなら外部コマンドはフルパスで書かんと フルパスで書かないといけなかったんですね…
修正してみたらできました、ありがとうございます! ようわからんがsavelogコマンドみたいなことがしたいのか >>396
「フルパスで書かなきゃいけない」のではない
$PATHを上書きするのがマズい これ1〜6までファイル全部消えるんじゃね? 5を6にリネーム~0を1にリネーム
そのあと最新のログを0にリネームじゃないかな
どっちにしろゴリ押し感半端ないが >>399
$PATHって環境変数ですよね…
何故気づかなかったんだろう
お恥ずかしい限りです あーそういうことか、403のお陰でやりたいことは分かった こうすればわかりやすいですかね
#!/bin/sh
DIR=/var/log/
FILE=dnsmasq.log;
START=0
for i in `seq 1 6`
do
DEC=`expr $i - 1`
cd $DIR
mv "${FILE}.${DEC}" "${FILE}.${i}"
done
cd $DIR
mv $FILE "${FILE}.${START}"
exit 0 個人的にexpr嫌いなのもあって$(())使っちゃうな
mv "${FILE}.$((i-1))" "${FILE}.$i"
あとseq間違ってね?
seq 6 1 -1 これだと全部ログ.0になっちゃいますね
ありがとうございます! そっちを使うほうが楽、ということを学習するにはまずは自分で書いてみて、大変だぜてことを理解しないと 昔solarisで見たlogrotateはshell scriptだった
どこかで見れれば参考になるかも あれはあんまりきれいじゃないから参考にしない方がいい この /usr/lib/newsyslog ね
http://www.tcp-ip.or.jp/~ikken/intra/check.txt X Windows System で,どの IMF が用いられているか判別する方法を考えている。
思い付いたのは $XMODIFIERS 環境変数を用いた
case $XMODIFIERS in
  *ibus)
    local _imf=ibus
    ;;
  *fcitx)
    local _imf=fcitx
    ;;
  *uim)
    local _imf=uim
    ;;
  *SCIM)
    local _imf=scim
    ;;
esac
なんだけど,$XMODIFIERS が必ず設定されているとは限らないし,なんか漏らしてる気がしてならん……。 ツールで投稿したら空白がエラいことになった。すまん。 Shell Scriptのコメントアウトに
# @(#) Foo is foo.
みたいな文字を書いておいて
$ what ./foo.sh
とやると
Foo is foo
という表示がでるというようなwhatコマンドがあるらしいのですが
手元のFedora26に見付かりません。($ dnf search what, $ dnf provides what)
どこかにありますでしょうか。 >>420
whatはかつて使われていたSCCSというソースコード管理システムに入っていたコマンド
現在はGNU CSSCがSCCSと同等の機能を提供している
なのでcsscというパッケージを探す
なければhttps://www.gnu.org/software/cssc/へGO! case文で
$1がhogeで、$2がhageの場合のみ処理Aを実行する
みたいなのできないでしょうか? $1にも$2にも含まれ得ない文字を区切りにして連結 >>422
ありがとうございます。依存地獄に嵌ってしまいあきらめました,教えてもらったのにすいません。
また,御礼がおそくなってもうしわけないです。 caseで実装するなら入れ子かね
しかしここでも髪の話するのか >>424
>>425
>>427
入れ子にできることを全然知らず
こんな感じかなでやってみたらいけました
皆さん短時間にありがとうございます
>>427
他意はありませんw すみません、bashでタブ区切りのファイルを配列に取り込む際、空の列が詰めて格納されてしまいます
そうならない方法はあるのでしょうか
exec < file.tsv
while read LINE
do
ARRAY=(${LINE})
done >>430
変数の参照部分を引用符で囲むとか。
#!/bin/sh -
exec < file.tsv
while read LINE; do
ARRAY=("$LINE")
done
echo "$ARRAY"
IFS の値を空にするとか。
#!/bin/sh -
IFS=
exec < file.tsv
while read LINE; do
ARRAY=($LINE)
done
echo $ARRAY あ,5ch ってコード貼るのまずいんだっけ。しくったな。
まあこんなくだらないコードに著作権云々関係ないかw >>430
bash なら mapfile がある(別名 readarray)
-t オプションで各行末尾の改行を取除く
mapfile -t ARRAY <file.tsv 検証した結果、IFSを改行のみにして読み込み、その文字列をCutで抜くで達成できました
こうしないと空文字の列が詰まってしまいました
IFS_BAK=IFS
IFS=$'¥n'
exec < file.tsv
while read LINE
do
echo "${LINE}" | cut -f1 >> tmp1.txt
echo "${LINE}" | cut -f2 >> tmp2.txt
done
IFS=IFS_BAK >>435
重箱の隅を突くようで悪いが,その書き方をするならシェバンは #!/usr/bin/bash
にしておけ。
$'string' は Bash の独自拡張だった気がする。 >>430
今ごろ勘違いに気づいた
mapfileじゃ全然見当外れじゃないか…なんかごめん
たとえば
IFS=$'\t'
line="${IFS}b"
このとき
a=(${line})
で
a=("" "b")
となるのを期待しているのだけど、実際にはクオートしていないので
a=( b)
と同じことになって、先頭の「空の列」は残らない
かといってクオートしたら
a=("${line}")
これはタブ区切りで分割されることなく行全体がそのままになるので意味がない…
ということだよね
>>435のようにファイルに書き出すだけなら、そうやってcutでやるのが扱いやすそうだけど
もしどうしても配列にする必要があるときは、こんな感じでどうだろう
https://ideone.com/uPfCwc
空だと消えてしまうなら空にならないよう何か入れとけばいいじゃない(配列にしてから取り除く)
という案 ■ このスレッドは過去ログ倉庫に格納されています