LoginSignup
8
12

More than 5 years have passed since last update.

シェルの習得中

Last updated at Posted at 2016-01-22

シェルの書き方、正規表現、文法を学習のために1つ1つ記述していきます。

  • 2月中めどで、だいたい網羅します。
  • 何かのお役に立てますと幸いです
  • シェルマスターに俺はなる

はじめに



#! /bin/bash -
# 冒頭の#!の次の値をプログラムへのパスとする
# オプションが1つ指定できる 例:#! /bin/awk -f
# 行末の「-」 はこの場合、「bashのオプションがこれ以上記述されない」という意味
# 特定のセキュリティ攻撃に対しての防御策となる




# 「--」 はオプションが終わりであることを示す
# 以降の文字列は引数として扱われる
ls -l --
# 結果
total 0
-rw-r--r--  1 t-yamamoto  staff  0  1 27 11:02 pr.txt


printf





# printfコマンド "文字列"を表す書式指定子「%s」 #改行「\n」
printf -- "hello world %s %s\n" yama tetsu
# 結果
hello world yama tetsu




# printfコマンド "正規表現を含む文字列"を表す書式指定子「%b」 "数字"を表す「%d」
printf -- '%b%b%b%b%d\n' "aaa\n" "bbb\n" "ccc\n" "ddd\n" "140"
# 結果
aaa
bbb
ccc
ddd
140




# ダブルコーテなし \はエスケープ文字とみなされる
printf -- '%b%b%b%b%d\n' aaa\n bbb\n ccc\n ddd\n 140
# 結果
aaanbbbncccndddn140




# コマンドを書いてみる `コマンド`
printf -- '%b %b %b %b %b\n' aaa bbb ccc ddd `mkdir aaa`
# 結果
aaa bbb ccc ddd

  # mkdirは実行された・・・?
  ls -l
  # 結果 実行されていた・・・ (%sでも一緒)
  total 8
  -rw-r--r--  1 t-yamamoto  staff  20  1 27 11:30 pr.txt
  drwxr-xr-x  2 t-yamamoto  staff  68  1 27 11:45 aaa




# \で特殊文字をエスケープできる ``をエスケープしてみる
printf -- '%b %b %b %b %b\n' aaa bbb ccc ddd \`mkdir aaa\`
# 結果
aaa bbb ccc ddd `mkdir
aaa`

  # 空白も特殊文字でした ※空白は引数の区切りとして扱われます
  # aaa\`は、5つ目の引数のあとに、改行\nがあるため、
  # 改行後に新たな行の1つ目の%bに対する引数として出力された



# \で特殊文字をエスケープできる ``と空白をエスケープしてみる
printf -- '%b %b %b %b %b\n' aaa bbb ccc ddd \`mkdir\ aaa\`
# 結果
aaa bbb ccc ddd `mkdir aaa`

 # できた・



# printfコマンド "数字"を表す「%d」 "%"を"%"でエスケープできる
printf -- '%d %% \n' "140"
# 結果
140 %



# 変数展開1  ダブルコーテに、シングルコーテで呼ばれる$ddd
ddd="ddd"
printf -- "%b" '$ddd\n'
# 結果
$ddd

# 変数展開2    ダブルコーテに、ダブルコーテで呼ばれる$ddd
printf -- "%b" "$ddd\n"
# 結果
ddd

# 変数展開3    シングルコーテに、ダブルコーテで呼ばれる$ddd
printf -- '%b' "$ddd\n"
# 結果
ddd

# 変数展開4    シングルコーテに、シングルコーテで呼ばれる$ddd
printf -- "%b" '$ddd\n'
# 結果
$ddd

# 呼び出し元のコーテーションがダブルかシングルかには関係なく、
# 記述先のコーテーションの変数展開ルールに従うようです




# 書式指定子なし1
printf "$ddd\n"
# 結果
ddd


# 書式指定子なし2
printf '$ddd\n'
# 結果
$ddd


# デフォルトは%bと同じ動きかと




# 1つの書式指定子「%d」(数字を表す書式指定)に、4つの引数
printf '%d\n' 1 2 "3"# 結果
1
2
3
-bash: printf: あ: invalid number
0

# 複数の引数でも、1つの書式指定子で扱える
# もちろん、書式指定に従わないとはじかれる
# なぜか、0とみなされる




# 2つの書式指定子「%d」(数字を表す書式指定)「%s」(文字列を表す書式指定)に、4つの引数を与えてみる
printf '%d %s\n' 1 2 "3"# 結果
1 2
3 あ




# 実験1  外部出力>
printf '%s\n' "aaaa" "bbbb" "cccc" "dddd" >pr.txt
cat pr.txt
# 結果
aaaa
bbbb
cccc
dddd


# 実験2    改行を削除して読み込み
printf '%s' `cat pr.txt`
# 結果
aaaabbbbccccdddd


# 実験3    外部出力を改行つけて読み込み
printf '%s\n' `cat pr.txt`
# 結果
# 1行ごとに読み込まれて%sに渡されていることがわかる
aaaa
bbbb
cccc
dddd


# 実験4    偶数行を空白区切りで出力
printf '%s %s\n' `cat pr.txt`
# 結果
aaaa bbbb
cccc dddd


# 実験5    変数格納
aaa="printf %b\n `cat pr.txt`"
$aaa
# 結果
aaaa
bbbb
cccc
dddd


# 実験6    変数に入れると少し勝手が変わる 
# 書式指定子をコーテーションでくくれない
# つまり、書式指定子と書式指定子の間に空白が入れられない
# タブの正規表現(\t)で区切る
aaa="printf %b\t%b\n `echo test` `cat pr.txt`"
$aaa
# 結果
test    aaaa
bbbb    cccc
dddd


# 実験7 ,で区切る
aaa="printf %b,%b\n `echo test` `cat pr.txt`"
$aaa
# 結果
test,aaaa
aaa,bbbb
cccc,dddd


# 実験8   #脱線  実験6の,を空白に置換
$aaa |sed 's#,# #g'
# 結果
test aaaa
bbbb cccc
dddd




tr


# 事前準備
printf '%s\n' "aaaa" "bbbb" "cccc" "dddd" >t_r_.txt
cat t_r_.txt
# 結果
aaaa
bbbb
cccc
dddd


# tr コマンドで標準入力の文字列から改行コードを除く
tr -d -- '\n' <./t_r_.txt
# 結果
aaaabbbbccccdddd




# tr コマンドで標準入力の文字列の改行をタブに置換
tr -- '\n' '\t' <./t_r_.txt
# 結果
aaaa    bbbb    cccc    dddd




# tr コマンドで標準入力の文字列の"aaaa"以外を"b"に置換
tr -c -- 'aaaa' 'b' <./t_r_.txt
# 結果
aaaabbbbbbbbbbbbbbbb

  # 改行もbに置換される


grep


# 事前準備
printf '%s\n' "aaaa" "bbbb" "cccc" "dddd" "-aaa" "AAAA" "1111" "2222">gr.txt
cat gr.txt
# 結果
aaaa
bbbb
cccc
dddd
-aaa
AAAA
1111
2222



# grepの使い方と正規表現

# デフォルトでは指定した文字列にマッチしたら表示してくれる
# [[:alnum:]] は、POSIXでのアルファベットと数字の文字クラス
grep -- [[:alnum:]] gr.txt
# 結果
aaaa
bbbb
cccc
dddd
-aaa
AAAA
1111
2222



# -v は指定した文字以外を抽出
grep "bbbb" gr.txt -v --
# 結果
aaaa
cccc
dddd
-aaa
AAAA
1111
2222



# -l はマッチしたファイル名を表示してくれる つまり、できる奴
grep [[:alnum:]] -l ./*.*
# 結果
./gr.txt




# -e はマイナス記号をオプションとみなさない つまり、親切
grep -e -aaa -- gr.txt
# 結果
-aaa




# -i は大文字小文字を区別しない つまり、おおらか
grep -i -- aaaa gr.txt
# 結果
aaaa
AAAA



# -q は何も表示しない エラーコードを返す つまり、冷静
grep -q -- aaaa gr.txt
# 結果
(出力なし)

#エラーコード出力
printf '%b\n' "$?"
# 結果
0




# POSIXでのアルファベットと数字の文字クラス[[:alnum:]]以外
# [[:alpha:]] アルファベット

# [[:blank:]]スペースとタブ

# [[:cntrl:]]制御文字

# [[:digit:]]数字

# [[:xdigit:]]16進数の数字

# [[:graph:]]スペース以外

# [[:lower:]]小文字

# [[:upper:]]大文字

# [[:print:]]印字可能な字

# [[:punct:]]句読点 というか記号

# [[:space:]]空白(を含む)




# ^行頭行末$
grep -i ^aaaa$ gr.txt
# 結果
aaaa
AAAA




# \ は特殊文字の打ち消し
grep \.\* gr.txt
# 結果
aaaa
bbbb
cccc
dddd
-aaa
AAAA
1111
2222
    # cat gr.txtと同じ




# grepは grep -E でegrepと同じEREの正規表現がつかえるようになる(後述)
# オプション無しのgrepでは、 BREの正規表現が使える


# BREの正規表現

# ブラケット表現 任意の一文字にマッチ
grep [abcse*¥] gr.txt
# 結果
aaaa
bbbb
cccc
-aaa




# 1 2 3を含む行にマッチ
grep [1-3] gr.txt
# 結果
1111
2222




# a b cを含む行にマッチ ※ロケール設定に依存
grep [a-c] gr.txt
# 結果
aaaa
bbbb
cccc
-aaa




# a A b B c Cを含む行にマッチ ※ロケール設定に依存
grep -i [a-c] gr.txt
# 結果
aaaa
bbbb
cccc
-aaa
AAAA




# 直前の1文字が、直前の文字も含めて2回繰り返されている
grep "a\{2\}" gr.txt
# 結果
aaaa
-aaa




# 直前の1文字が直前の文字も含めて2回以上、4回未満繰り返されている
grep "a\{2,4\}" gr.txt
# 結果
aaaa
-aaa



# "aaaa"の行を抽出
grep "^a\{4\}$" gr.txt
# 結果
aaaa




# 再利用 ホールドスペース \(xxxx\) ちょっとかわいい
grep "\(a\)" gr.txt
# 結果
-aaa
aaaa




# "a"が2回登場する \1-9
grep "\(a\)\1" gr.txt
# 結果
-aaa
aaaa




# EREの正規表現
# BREの\{\}と同じ
grep -E "a{1,2}" gr.txt
# 結果
-aaa
aaaa




# 直前の正規表現が1回以上出現 aaaaはでない aaaaaはでる
grep -E "aaaa.+" gr.txt
# 結果
(出力なし)




# 直前の正規表現が0回または1回出現 aaaaは出る aaaaaはでない
grep -E "aaaa.?" gr.txt
# 結果
aaaa




# |でorがつかえる
grep -E "^aaa|^bbb" gr.txt
# 結果
aaaa
bbbb




# ()で囲まれた部分にマッチング bbbbかaaaa
grep -E "^(bbbb|aaaa)$" gr.txt
# 結果
aaaa
bbbb




sed




# sed による置換 

# 区切り文字はなんでもよい
# 区切り文字は、置換対象になる場合、\でエスケープする必要があるので、"/"は避けるべし
  # /を区切り文字にした煩雑な例 ./aaa/bbb/ccc.txt を ./ddd/eee/fff.txtに置換
  sed s'/.\/aaa\/bbb\/ccc.txt/.\/ddd\/eee\/fff.txt/g'

# ";"が多い気がする。私は"#"が好き
# 例:sed 's;yama;tetsu;'

# printfコマンドの"aaaa"を"bbbb"に置換
printf "%b" "aaaa\n" "bbbb\n" |sed 's#aaaa#bbbb#'

# 結果
bbbb
bbbb


# 後ろに"g"をつけると、全て置換
# 後ろに数字nをつけると、n番目を置換

   # 例 s/aaa/bbb/    1つめのaaaだけをbbbに置換
   # 例 s/aaa/bbb/1    1つめのaaaだけをbbbに置換
   # 例 s/aaa/bbb/2    2つめのaaaだけをbbbに置換
   # 例 s/aaa/bbb/g    すべてのaaaだけをbbbに置換


# n番目って何を基準に決めてるの??

# 下記コマンドをパイプラインでsedに渡して検証
printf "%b" "a\n" "a\n" && printf "%b" "a\n"
# このコマンドの出力結果は以下
a
a
a

# 実験1 なし
(printf "%b" "a\n" "a\n" && printf "%b" "a\n")|sed 's#a#b#'
# 結果
b
b
b


# 実験2 1
(printf "%b" "a\n" "a\n" && printf "%b" "a\n")|sed 's#a#b#1'
# 結果
b
b
b


# 実験3 2
(printf "%b" "a\n" "a\n" && printf "%b" "a\n")|sed 's#a#b#2'
# 結果
a
a
a


# 実験4  1個目のaをaaにしてみる
(printf "%b" "aa\n" "a\n" && printf "%b" "a\n")|sed 's#a#b#'
# 結果
ba
b
b


# 実験5
(printf "%b" "aa\n" "a\n" && printf "%b" "a\n")|sed 's#a#b#1'
# 結果
ba
b
b


# 実験6
(printf "%b" "aa\n" "a\n" && printf "%b" "a\n")|sed 's#a#b#2'
# 結果
ab
a
a

# 実験7
(printf "%b" "aa\n" "a\n" && printf "%b" "a\n")|sed 's#a#b#g'
# 結果
bb
b
b


# 結論
# 行ごとにn番目という意味




# sed '場所(行) コマンド'

# printfで2行目に出力されるaaだけをbbに置換する方法
printf "%b" "aa\n" "aa\n" |sed '2 s#a#b#g'
# 結果
aa
bb



# printfで最終行に出力されるaaだけをbbに置換する方法 $
printf "%b" "aa\n" "aa\n" "aa\n"|sed '$ s#a#b#g'
# 結果
aa
aa
bb




# find に渡す
find ./ |sed 's#aaaa#bbbb#g'
# 結果
#./aaaa/aaaa.txt → ./bbbb/bbbb.txt




# 検索箇所から一番階層の近い場所にある1個目の"aaaa"を"bbbb"に置換
find ./ |sed 's#aaaa#bbbb#1'
# 結果
# ./aaaa/aaaa.txt → ./bbbb/aaaa.txt




# 利用ファイル準備
printf '%s\n' "aaaa" "bbbb" "AAAA" "BBBB" "-aaa" >sd.txt
cat sd.txt
# 結果
aaaa
bbbb
AAAA
BBBB
-aaa




# catで渡す
cat sd.txt |sed 's#aaaa#bbbb#1'
# 結果
bbbb
bbbb
AAAA
BBBB
-aaa




# -e で複数のコマンドを羅列できる
cat sd.txt |sed -e 's#aa#bb#1' -e '1 s#AA#BB#1'
# 結果
bbaa
bbbb
AAAA
BBBB
-bba




# 接頭が「-」は消し、冒頭 "^" を "mkdir " に置換
cat sd.txt |sed -e 's#^-##g' -e 's#^#mkdir #1'
# 結果
mkdir aaaa
mkdir bbbb
mkdir AAAA
mkdir BBBB
mkdir aaa




# 実行
cat sd.txt |sed -e 's#^-##g' -e 's#^#mkdir #1'|sh
# 結果
total 8
drwxr-xr-x  2 t-yamamoto  staff  68  1 27 16:43 1111
drwxr-xr-x  2 t-yamamoto  staff  68  1 27 16:43 2222
drwxr-xr-x  2 t-yamamoto  staff  68  1 27 16:43 AAAA
-rw-r--r--  1 t-yamamoto  staff  40  1 27 15:45 a.txt
drwxr-xr-x  2 t-yamamoto  staff  68  1 27 16:43 bba
drwxr-xr-x  2 t-yamamoto  staff  68  1 27 16:43 bbaa
drwxr-xr-x  2 t-yamamoto  staff  68  1 27 16:43 bbbb
drwxr-xr-x  2 t-yamamoto  staff  68  1 27 16:43 cccc
drwxr-xr-x  2 t-yamamoto  staff  68  1 27 16:43 dddd




# aaを含む列に対してのみ、aをbに置換
(printf "%b%b" "aaaa\n" "baab\n" && printf "%b%b" "abba\n" "aaaa\n" )|sed '/.*aa.*/ s#a#b#g'
# 結果
bbbb
bbbb
abba
bbbb




# sed '/文字列や正規表現/,/文字列や正規表現/ コマンド'
# aaを含む列から、baを含む列までの間で、aをbに置換
(printf "%b%b" "aaaa\n" "baab\n" && printf "%b%b" "abba\n" "aaaa\n" )|sed '/.*aa.*/,/.*ba.*/ s#a#b#g'
# 結果
bbbb
bbbb
abba
bbbb




# "aaaa"を含まない行を置換 !
cat sd.txt |sed '/aaaa/ !s#a.*#b#g'
# 結果
aaaa
bbbb
AAAA
BBBB
-b




# \で行を指定する区切り文字を変える
cat sd.txt |sed '\#aaaa# !s#a.*#b#g'
# 結果
aaaa
bbbb
AAAA
BBBB
-b




# sed -n は修正された行の出力をしない
# pコマンドで指定した行をそのまま出力する 1行目を出力
printf "%b%b" "aaaa\n" "baab\n" "aaa\n" |sed -n '1,2p'
# 結果
aaaa
baab



cut


## printfで出力された"aa,bb"を、,で区切り2フィールド目を出力
printf "%b,%b" "aa" "bb" |cut -d , -f 2
# 結果
bb




# /etc/passwdからホームディレクトリのフィールドを抽出 -d -f
cut -d : -f 6 /etc/passwd




# 行頭の1〜3文字目を抽出 -c
printf "%b" "123456\n" "654321\n" | cut -c 1-3
123
654




join


# 事前ファイル準備
printf "%b %b\n" "#Name" "BloodType" "Takashi" "A" "Itao" "B">jn.txt
printf "%b %b\n" "#Name" "Sex" "Takashi" "Man" "Itao" "Man">jn2.txt
cat jn.txt jn2.txt
# 結果
#Name BloodType
Takashi A
Itao B
#Name Sex
Takashi Man
Itao Man




# join でマージ
join jn.txt jn2.txt
# 結果
#Name BloodType Sex
Takashi A Man
Itao B Man




# 2つのファイルで行の順番が異なる場合、ソートする必要がある
# 事前ファイル準備
printf "%b %b\n" "#Name" "BloodType" "Itao" "B" "Takashi" "A">jn.txt
printf "%b %b\n" "#Name" "Sex" "Takashi" "Man" "Itao" "Man">jn2.txt
cat *jn*.txt
# 結果
#Name BloodType
Itao B
Takashi A
#Name Sex
Takashi Man
Itao Man




# sort
sort jn.txt>jn_sort.txt
sort jn2.txt>jn2_sort.txt
cat *sort*
# 結果
#Name Sex
Itao Man
Takashi Man
#Name BloodType
Itao B
Takashi A




# 並べ替えしたファイルをjoin
join *sort*
# 結果
#Name Sex BloodType
Itao Man B
Takashi Man A




# ヘッダを削除してjoin  sed'/xxx/d' sedのdeleteコマンドで#を消す
join *sort* |sed '/#/d'
# 結果
Itao Man B
Takashi Man A



# jn2.txtの1フィールド目をキーにしてjoin
  # join -1 file1のキー -2 file2のキー file1 file2
join -2 1 jn.txt jn2.txt
#Name BloodType Sex
Takashi A Man
Itao B Man




# 区切り文字が:のファイルをjoin
printf "%b:%b\n" "yama" "/bin/bash">logs.txt
printf "%b:%b\n" "yama" "yama_group">grp.txt
cat logs.txt grp.txt
# 結果
yama:/bin/bash
yama:yama_group

# join -t
join -t : grp* logs*
# 結果
yama:yama_group:/bin/bash




awk


# 事前準備
printf "%b\n" "yama:/bin/bash" "Itou:/bin/ksh" >aw.txt
cat aw.txt
# 結果
yama:/bin/bash
Itou:/bin/ksh



#awk option '{コマンド}' Filename

# -F 入力のフィールド区切り文字を:にする例
# $1は1フィールド目を出力
awk -F : '{print $1}' aw.txt
# 結果
yama
Itou

# $0は全てのフィールド
awk -F : '{print $0}' aw.txt
# 結果
yama:/bin/bash
Itou:/bin/ksh




# -v 環境変数設定
# OFS 出力の区切り文字
awk -F : -v 'OFS=####' '{print $1,$2}' aw.txt
# 結果
yama####/bin/bash
Itou####/bin/ksh




# 文字列と一緒に出力
awk -F : -v 'OFS=\t' '{print "User:: "$1,"LoginShell:: "$2}' aw.txt
# 結果
User:: yama LoginShell:: /bin/bash
User:: Itou LoginShell:: /bin/ksh




# 文字列と一緒に出力2 printf
awk -F : '{printf "User:: %s\tLoginShell:: %s \n",$1,$2}' aw.txt
# 結果
User:: yama LoginShell:: /bin/bash
User:: Itou LoginShell:: /bin/ksh




# $NFで最終フィールドを取得
printf "%b\n" "a:b:c:d:e:f" "" "a:b:c:d:e:f" |awk -F : '{printf "LastField:: %s \n",$NF}'
# 結果
LastField:: f
LastField::
LastField:: f




# 空行以外を全て出力 $0は全てのレコード
printf "%b\n" "a:b:c:d:e:f" "" "a:b:c:d:e:f" |awk -F : 'NF > 0 {print $0}'
# 結果
a:b:c:d:e:f
a:b:c:d:e:f


# フィールド区切りとレコード区切り

# :をフィールド区切りにして1〜4フィールド出力
printf "%b\n" "a:b:c:d:e:f" "" "a:b:c:d:e:f" |awk -F : 'NF > 0 {print $1,$2,$3,$4}'
# 結果
a b c d
a b c d




# /をレコード区切りにして1〜4レコード出力
# レコードセパレータは任意の1文字(正しい情報じゃないかもしれない)
printf "%b" "a:b/c:d/e:f/g:h/" |awk -v 'RS=/' '{print$1,$2,$3,$4}'
# 結果
a:b
c:d
e:f
g:h



# フィールド区切りとレコード区切りを一緒に使う
printf "%b" "a:b/c:d/e:f/g:h" | awk -F : -v 'OFS=\t' -v 'RS=/' -v 'ORS=\n' '{print$1,$2}'
# 結果
a   b
c   d
e   f
g   h


# 空白区切りでならべる 改行をレコード区切りに指定して、半角スペースに置換
printf "%b\n" "a:b:c:d:e:f" "" "a:b:c:d:e:f" |awk -F : -v 'RS=\n' -v 'ORS= ' 'NF > 0 {print $0}' |tr ":" " "|sed 's# $##g'
#結果
a b c d e f a b c d e f t




# 1〜4フィールドだけ取り出してならべる 改行をレコード区切りに指定して、半角スペースに置換
printf "%b\n" "a:b:c:d:e:f" "" "a:b:c:d:e:f" |awk -F : -v 'RS=\n' -v 'ORS= ' 'NF > 0 {print $1,$2,$3,$4}'
# 結果
a b c d a b c d




# 上のaをbに置換 gsub関数
printf "%b\n" "a:b/c:d/e:f/g:h" | awk -F : -v 'OFS=\t' -v 'RS=/' -v 'ORS=\n' '{gsub("a","b");print$1,$2}'
b   b
c   d
e   f
g   h



# aをb bをc cをd dをe eをf fをg gをh に順番に置換
printf "%b\n" "a:b/c:d/e:f/g:h" | awk -F : -v 'OFS=\t' -v 'RS=/' -v 'ORS=\n' '{gsub("a","b");gsub("b","c"); gsub("c","d");gsub("d","e");gsub("e","f");gsub("f","g");gsub("g","h");print$1,$2}'
# 結果
h   h
h   h
h   h
h   h


sort


# sort -t: -k1.1,1.2
# -t 区切り文字を指定
# -k キーとなる文字の開始フィールド.開始文字の位置,終了フィールド.終了文字の位置
printf "%b\n" "ab:ba" "ba:ab" |sort -t: -k1.2,1.2
# 結果
ba:ab
ab:ba

# r
sort ./passwd.txt -k2r -t:
# kekka
_krbfast:*:246:-2:Kerberos FAST Account:/var/empty:/usr/bin/false
daemon:*:1:1:System Services:/var/root:/usr/bin/false
root:*:0:0:System Administrator:/var/root:/bin/sh
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false


# f は大文字と小文字を区別しない
# d 辞書順
sort ./passwd.txt -k2d -t:
# kekka
root:*:0:0:System Administrator:/var/root:/bin/sh
daemon:*:1:1:System Services:/var/root:/usr/bin/false
nobody:*:-2:-2:Unprivileged User:/var/empty:/usr/bin/false
_krbfast:*:246:-2:Kerberos FAST Account:/var/empty:/usr/bin/false


# uniq で重複排除
printf "%b\n" "aa:ba" "aa:ab" "aa:cc" "aa:dd" "aa:cc" |sort -t: -k2 |uniq
#結果
aa:ab
aa:ba
aa:cc
aa:dd


# 重複してない行だけ表示
printf "%b\n" "aa:ba" "aa:ab" "aa:cc" "aa:dd" "aa:cc" |sort -t: -k2 |uniq -u
# 結果
aa:ab
aa:ba
aa:dd



# 重複行のみ
printf "%b\n" "aa:ba" "aa:ab" "aa:cc" "aa:dd" "aa:cc" |sort -t: -k2 |uniq -d
# 結果
aa:cc



# 登場回数も表示
printf "%b\n" "aa:ba" "aa:ab" "aa:cc" "aa:dd" "aa:cc" |sort -t: -k2 |uniq -c
# kekka
   1 aa:ab
   1 aa:ba
   2 aa:cc
   1 aa:dd

#もう一回sort
printf "%b\n" "aa:ba" "aa:ab" "aa:cc" "aa:dd" "aa:cc" |sort -t: -k2 |uniq -c |sort
  1 aa:ab
  1 aa:ba
  1 aa:dd
  2 aa:cc

# 登場回数順に表示
printf "%b\n" "aa:ba" "aa:ab" "aa:cc" "aa:dd" "aa:cc" |sort -t: -k2 |uniq -c|sort -r |awk '{print $2}'
# 結果
aa:cc
aa:dd
aa:ba
aa:ab



行指定の方法


# 今北産業の(ファイルの末尾3行)表示
tail -f -n 3 passw*
# kekka
root:*:0:0:System Administrator:/var/root:/bin/sh
daemon:*:1:1:System Services:/var/root:/usr/bin/false
_krbfast:*:246:-2:Kerberos FAST Account:/var/empty:/usr/bin/false


# awkのFNR で行番号を指定
printf "%b\n" "a" "b" "c" |awk 'FNR <= 1'
# 結果
a


# sedのqコマンドで指定した行まで表示
printf "%b\n" "a" "b" "c" |sed 2q
# 結果
a
b


# headコマンド
printf "%b\n" "a" "b" "c" |head -2
# 結果
a
b



ここからは自由に



# cdコマンドを作りかえる
cd () { command cd "$@"; x=$(pwd); PS1="${x##*/}\$"; }



# while文 ユーザー名とログインシェルをタブ区切りで取り出す
# また、変数aの文字列aをwhileループ内でbに変更
a="a"

while IFS=: read user pass uid gid fullname homedir logshell
do
  printf "%b" "${user}\t" "${logshell}\n"
  a="b"
done </etc/passwd

echo $a # aはbになる



# 上と同じことを別の方法で catしてパイプで渡してみる
# 変数aの文字列aをwhileループ内でbに変更
a="a"

cat /etc/passwd |
while IFS=: read user pass uid gid fullname homedir logshell
do
  printf "%b\t" "${user}\t" "${logshell}\n"
  a="b"
done

echo $a # aはaのまま つまり、パイプで渡すと外部変数は変更されない・・



# 上と同じこと2
# RSとORSはデフォルトと同じなので別にいらないが、あえて意識した
cat /etc/passwd |awk -F : -v 'RS=\n' -v 'ORS=\n' -v 'OFS=\t' '{print $1,$7}'


# 上と同じこと3
# プロセス置換 <(list)
awk -F : -v 'RS=\n' -v 'ORS=\n' -v 'OFS=\t' '{printf "%s\t%s\n",$1,$NF}' <(cat /etc/passwd)


# 上と同じこと4
a="a"

while IFS=: read user pass uid gid fullname homedir logshell
do
  printf "%b" "${user}\t" "${logshell}\n"
  a="b"
done< <(cat /etc/passwd)

echo $a #もちろんaはbに 

#コマンドの結果をreadに渡して、ループ内で外部変数の書き換えを行う際には、
#bashの機能であるプロセス置換を用いることにより、一時ファイルを作らなくて良くなる




# 変数の展開
a="abcd/efgh/ijkl/mnop"

# 先頭から1文字目だけ表示
printf "%b\n" ${a::1}
a

# 先頭から2文字目まで表示
printf "%b\n" ${a::2}
ab


# 先頭から1文字目だけ表示 上とおなじこと
printf "%b\n" ${a:0:1}
a


# 2文字目から2文字表示
printf "%b\n" ${a:1:2}
bc



# abcが定義されていない場合にnodefと返す
printf "%b\n" ${abc-nodef}
nodef




# abcが定義されていない場合にnodefと返しスクリプトを強制終了
printf "%b\n" ${abc?nodef}
-bash: abc: nodef
8
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
12