動機

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. 把多的斷行吃掉 故最後會變成
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的使用時機