CU--Shell程式設計大賽

fjzcau發表於2011-05-19

ChinaUnix技術實踐之四----Shell程式設計大賽!

問題1:
用最簡潔的命令列出當前目錄下的一級子目錄,可以不包含隱藏目錄(目錄名以.開頭的目錄)

[@more@]

--答案:
1)tree -d -L 1
2)ls -d */
3)du --max-depth=1
4)find ./* -maxdepth 0 -type d
5)find * -type d -prune -print
6)find ! -path . -type d -prune -print
7)ls -F|grep "/"


問題2:
GNU sed 提供了-i選項,為什麼有人說sed -i 並不象 ed 一樣真正的編輯檔案?(提示:觀察檔案改變前後的inode)
--答案:
區別在於互動式,因為sed只適用於非互動式的場合(可以認為這是一種弊端,因為會有臨時檔案產生)。
同時,使用sed -i編輯檔案會導致檔案的inode改變。
ed 是直接編輯檔案,sed 是生成臨時檔案,然後改名實現的。

問題3:
用shell寫一個cgi指令碼,提供一個簡單的webmail介面,將本地的一個檔案透過web伺服器傳送到指定的郵箱
--答案:
#!/bin/bash
echo -e "Content-type: text/htmln"

if (( $# == 0 ));then
# main
cat <

$(date +%F) 簡單傳送郵件CGI






收件人:&nbsp


標&nbsp&nbsp&nbsp&nbsp題:&nbsp


正&nbsp&nbsp&nbsp&nbsp文:&nbsp


附&nbsp&nbsp&nbsp&nbsp件:&nbsp







EOF
else
if [[ ${QUERY_STRING} == "send" ]] && [[ ${REQUEST_METHOD} = POST ]];then
cd /tmp
cat - >/tmp/$.mf
typeset -x _F=$(awk '{if($0~/^Content-Disposition.+filename/)print gensub(".+filename="(.+)".*","
$.mf)
typeset -x State="${CONTENT_TYPE##*=}"
if [ ! -z ${_F} ];then
typeset -x $(awk 'BEGIN{FS="rn";RS=ENVIRON["State"]}{if($2~/Address/)print "rcptto=x22"$4"x22";
if($2~/Subject/)print "subject=x22"$4"x22"
if($2~/Info/)print "info=x22"$4"x22"
if($2~/filename/)printf("%s",$5)>ENVIRON["_F"]
}' $.mf)
echo "${info}"|mutt -a ${_F} -s "${subject}" ${rcptto}
else
echo "${info}"|mutt -s "${subject}" ${rcptto}
fi
rm -f $.mf ${_F}
fi
cat <

$(date +%F) 簡單傳送郵件CGI




郵件已經傳送,請查收.



Redirect





EOF
fi


問題4:
awk -F'' 與 awk -F '' 一樣嗎?
--答案:
不一樣,-F''的話awk無法解讀-F變數。
awk -F '' 可以使用 NULL 為分隔符。
awk -F'' 不能使用 NULL 為分隔符。起引號內必須賦值.


問題5:
這條語句有什麼作用?
sed -if /script/scr.sedcc test.txt
--答案:
sed呼叫檔案/script/scr.sedcc執行,對test.txt直接處理


問題6:
#!/bin/sh
# the next line restarts using tclsh
exec tclsh "$0" "$@"

是如何執行的?與"#!/usr/local/bin/tclsh"相比,它有什麼優點?

--答案:
1)執行過程:
第一種會導致sh和tclsh都去執行指令碼,exec僅透過sh執行,sh先執行指令碼,把第二行作為註釋,
然後執行第三行,當執行到exec的時候停止sh的處理,轉而啟用tclsh,這個時候tclsh會重新將整個指令碼再執行一次,
由於這個時候第二行末尾有個續行符,所以tclsh將所有三行都當成了註釋。
2)優點
a)tclsh指令碼可以位於任意位置(只要是在$PATH中,shell能找到的就行),
也就是說並不需要講絕對路徑寫到指令碼中去
b)它能夠突破檔名為30個字元的限制
c)這種寫法甚至在tclsh本身是shell指令碼的時候也能執行

問題7:
#!/bin/sed -f" shebang 後可有其它字元嗎?為什麼?
--答案:
不能!!!(空格可以有)
對於Shebang lines(即#!打頭的行),一般只允許在直譯器後面跟一段空格,
這也就是為什麼所有sed的引數不能分開的應用於Shebang line的原因
(比方說你不能想當然的寫成#!/usr/bin/sed -E -f,因為這是不允許的)。

問題8:
GNU awk的$1=$1到底有什麼作用?$0=$0呢?
--答案:
$1=$1 用當前的OFS重構 $0 NF 不改變
$0=$0 用當前的 FS重構 $1..$N NF 會改變


問題9:
寫一個shell指令碼,輸出CU現有的版面和相應版主,並統計有多少個版面及多少個版主。
--答案:

#--------------------------
#!/bin/bash
:>moderator_num
main_url="
"
wget -q "$main_url" -O index.html
Total_pages=`grep -o '^.*a>' index.html | wc -l`
sub_url=(`grep -o '^
.*a>' index.html | grep -o 'forum-.*html' | tr 'n' ' '`)
sub_page=(`grep -o '^
.*a>' index.html | awk -F'[<>]' '{print $3}' | tr 'n' ' '`)
for (( i=0; i moderator_list=(`wget -qO- $main_url/${sub_url[i]} | sed -rn '/^

/{n;p}' | sed 's/]*>//g' | awk -F: '{print $2}'`)
echo ${#moderator_list[@]} >> moderator_num 2>&1
echo -e "${sub_page[i]}: ${moderator_list[@]}"
done
Total_moderators=`awk '{sum+=$1}END{print sum}' moderator_num`
echo "Total pages of Chinaunix: $Total_pages"
echo "Total moderator of Chinaunix: $Total_moderators"

#-------------------------------
#!/bin/bash
#
PATH=${PATH}:/sbin:/usr/sbin:/usr/local/bin
Url="
"
N=0
curl --connect-timeout 10 -m 60 --retry 5 -A "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" ${Url} -o /tmp/tempfile 2>/dev/null
awk '{if($0~"bold subject"){getline;getline;printf("%s %sn",gensub("href..(.+)"","
/tmp/tempfile >/tmp/tempfile1
while read Url1 Name;do
let N++
printf "%-2s -- %-20s%-20sn" ${N} ${Name} "[${Url}/${Url1}]" >>/tmp/tempfile3
curl --connect-timeout 10 -m 60 --retry 5 -A "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)" ${Url}/${Url1} -o /tmp/tempfile2 2>/dev/null
awk 'BEGIN{FS="[<>]"}{if($1=="版主: ")for(i=3;i>/tmp/tempfile3
doneawk '{printf("%-15s",($1=="版主:")?"["$2"] ":"nn"$0"n")}' /tmp/tempfile3
echo '#------------------------------------------------------------------#'
awk '{if($0~/^版主/){A[$0]++}else{B[$0++]}}END{printf("CU現有版面[%d]t版主[%d]個n",length(B),length(A))}' /tmp/tempfile3
rm -f /tmp/tempfile*

#----------------------------------
#!/bin/bash

# root url
RURL="
"

# 獲取版塊
# in: 如果無引數呼叫,獲取首頁的所有版塊;
# 如果提供一個引數呼叫, 返回該版塊內的子版塊
# out: 輸出獲取到的版塊名
function get_forums()
{
if [ -z $1 ]; then
curl $RURL -o- 2>/dev/null | grep -Eo 'forum[^"]+.html' | sort -u
else
curl $RURL/$1 -o- 2>/dev/null | grep -Eo 'forum[^"]+.html' |
grep -v "$1" | sort -u
fi

}

# 獲取指定版塊的版塊名
# in: 版塊, 如: forum-216-1.html
# out: 輸出該版塊的名字
function get_forum_name()
{
curl $RURL/$1 -o- 2>/dev/null | grep forumheader -A 1 |
iconv -f GBK -t UTF-8 |
cut -d'>' -f2 | cut -d '}

# 獲取指定版塊的所有版主
# in: 版塊, 如: forum-216-1.html
# out: 輸出該版塊的所有版主
function get_moderators()
{
test -z $1 && echo "usage $0 curl $RURL/$1 -o- 2>/dev/null |
grep modedby -A 1 | iconv -f GBK -t UTF-8 |
tr ',' 'n' |
cut -d'>' -f2 | cut -d' grep -Ev '^
}

function main()
{
my_forums=$(get_forums)
for x in $my_forums; do
get_forum_name $x
echo -e "t$(get_moderators $x | xargs)"
my_sub_forums=$(get_forums $x)
for sub_x in $my_fub_forums; do
get_forum_name $sub_x
echo -e "t$(get_moderators $sub_x | xargs)"
done
done
}

TMPFILE=$(mktemp)
main | tee $TMPFILE

# 版塊數
forum_num=$(grep -Ev '^[[:space:]]' $TMPFILE | grep -Ev '^ | wc -l)
echo "ChinaUnix共有$forum_num個版塊"

# 版主數
moderator_num=$(grep -E '^[[:space:]]' $TMPFILE | tr -d 't' | tr ' ' 'n' | grep -Ev '^ | wc -l)
echo "ChinaUnix共有$moderator_num個版主"

rm -f $TMPFILE


問題10:
人機五子棋。原始規則(無禁手),最好加上標準規則,三手交換(即黑下第二手之後白可以提出交換),
五手兩打,黑三三禁手,黑四四禁手,黑長連禁手(超過5個子相連),逢五無禁手。白無禁手,長連也算勝。
關鍵在於人機對下。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/22661144/viewspace-1050083/,如需轉載,請註明出處,否則將追究法律責任。

相關文章