動機
onlinejudge居然有bash的題目!! 這麼有趣的東西當然是解爆阿!!
抱怨
有的時候會出現
rbash: ./prog.sh: Permission denied
這個時候就是只能調整輸入像用pipe等等
題目
目前只有4題
- 192
- 193
- 194
- 195
192
cat words.txt | tr ' ' '\n' | sed '/^[[:space:]]*$/d' | sort | uniq -c | nawk '{print $1" "$2}' | sort -r -n -k 1 | nawk '{print $2" "$1}'
bash做為一個奇怪的PL
bash可以想成只有string的PL
那要怎麼表現array? 用delimiter區分,常見的是
- space
- newline
- comma
- etc…
第一步: 多個array合成一條array
- 先把空白換成斷行
- 把多的斷行吃掉 故最後會變成
1 2 3 =>
1
2
3
cat words.txt | tr ' ' '\n' | sed '/^[[:space:]]*$/d'
第二步: 計數
先排好,再計算重複的單字
| sort | uniq -c
第三步: 依題目調整輸出
| nawk '{print $1" "$2}' | sort -r -n -k 1 | nawk '{print $2" "$1}'
193
cat file.txt | egrep "^\([0-9][0-9][0-9]\) [0-9][0-9][0-9][-][0-9][0-9][0-9][0-9]$|^[0-9][0-9][0-9][-][0-9][0-9][0-9][-][0-9][0-9][0-9][0-9]$"
這題就是regex
194
cat file.txt | awk '
{
for (j=1; j<=NF; j++) {
M[NR, j] = $j
}
}
END {
for (i=1; i<=NR; i++) {
for (j=i+1; j<=NF; j++) {
tmp = M[i,j]
M[i,j] = M[j,i]
M[j,i] = tmp
}
if (NR > NF) {
for (j=NF+1; j<=NR; j++) {
tmp = M[i,j]
M[i,j] = M[j,i]
M[j,i] = tmp
}
}
}
for (i=1; i<=NF; i++) {
for (j=1; j<NR; j++) {
printf "%s ", M[i,j]
}
print M[i, NR]
}
}'
awk與sed的使用時機
同樣都是一行一行處理,但是 sed只處理單行,把每行當成string awk可以深入到每個item(在awk叫field),把每行當成array
所以一般來說sed常看到用在replace或是print需要的一整行 而awk會用在挑出在那一行中需要的item
awk的運作方式
一次讀一行,同時幫你分成array(index from 1)
哪要怎麼知道現在讀到第幾行?
NR
哪要怎麼知道現在的array長度?
NF
所以如果寫成python會像
with open('file.txt') as f:
NR = 0
for line in f:
NR += 1
arr = ' '.split(line)
your_awk_prog(arr, NF=len(arr), NR=NR)
除了針對每一行的部分,還有
- awk啟動前(還沒讀檔,像是變數初始化的階段)
- awk讀完當案後(讀到EOF) 可以執行的hook
195
chmod a+x file.txt # for handling Permission denied
sed '10q;d' file.txt
就是sed參考前面的 awk與sed的使用時機