bash-handbook [論壇 - Ubuntu 文件資源]


正在瀏覽:   1 名遊客


 到底部   前一個主題   下一個主題  [無發表權] 請登錄或者註冊



bash-handbook
會員五級
註冊日期:
2012/4/22 10:50
所屬群組:
已註冊使用者
等級: 37
HP : 0 / 901
MP : 671 / 29295
EXP: 6
離線
bash-handbook (中文版)」,之前我有提過「1」「2」,

也有列在「如何執行指令」這個索引。

再次貼這個連結在這個論壇的「Ubuntu 文件資源」。


可以搭配

* man bash
* info bash
* 「Learn X in Y minutes {Where X=bash} (中文版)」-「GitHub (中文版)」

來閱讀


例如這個「回覆」,就有列對照閱讀的連結。

供大家參考




## 其他相關的

* man 1 sh
* man 1posix sh

執行


$ whatis sh



顯示


sh (1) - command interpreter (shell)
sh (1posix) - shell, the standard command language interpreter




## Package

* manpages
* manpages-posix
* bash-doc

## 中文文件

* 鳥哥的 Linux 私房菜
* 阿旺的 Linux 開竅手冊 (連結紀錄在這)

## 相關討論

* 回覆: 關於shell script的問題 - 「#13」「#3」,「#4」,「#7」,「#8」,「#9」,「#10」,「#11」,「#12

2016/12/24 13:06
應用擴展 工具箱
回覆: bash-handbook
會員五級
註冊日期:
2012/4/22 10:50
所屬群組:
已註冊使用者
等級: 37
HP : 0 / 901
MP : 671 / 29295
EXP: 6
離線
剛好看到這個「範例」,可以用來舉例說明。

原本的例子使用「sed」,「範例1」和「範例2」先改用「awk」來實做,如同「cut」切欄位的方式,
下面「範例3」和「範例4」再提另一種「sed」的作法。

範例1. $ echo 'Product Revision: 123456' | awk '{printf $3}'
範例2. $ echo 'Product Revision: 123456' | awk 'BEGIN{FS=": "}{printf $2}'

說明:
「範例1」是以預設的分隔字元「空白」,所以是印欄位3,也就是「$3」。
「範例2」是設定分隔字元為「: 」,所以是印欄位2,也就是「$2」。

上面兩個範例,均顯示


123456




再來改用讀檔的方式,也就是該案例原本要達成的需求。

先執行下面的指令,產生一個範例檔案「ex.txt」


$ echo 'Product Revision: 123456' > ex.txt



執行下面指令,顯示範例檔案「ex.txt」的內容


$ cat ex.txt



顯示


Product Revision: 123456



然後上面的範例就可以改成如下,
主要是將「echo 'Product Revision: 123456'」改成「cat ex.txt」。

範例1.


$ cat ex.txt | awk '{printf $3}'



範例2.


$ cat ex.txt | awk 'BEGIN{FS=": "}{printf $2}'



顯示


123456



不過有另一個指令「cut」也可以達成


執行


$ echo 'Product Revision: 123456' | cut -d ' ' -f 3



顯示


123456



執行


$ cut -d ' ' -f 3 ex.txt



顯示


123456




================================================================================

## 範例3

執行


$ echo 'Product Revision: 123456' | xargs printf "%s\n"



這樣會列出三行如下


Product
Revision:
123456



然後搭配「sed」,只印出第三行


$ echo 'Product Revision: 123456' | xargs printf "%s\n" | sed -n '3p'



將「echo 'Product Revision: 123456'」這一段改成讀檔的方式。


$ cat ex.txt | xargs printf "%s\n" | sed -n '3p'



顯示


123456




================================================================================

## 範例4

範例三的方式,
是將「Product Revision: 123456」
透過「printf」來拆成三行,
然後再透過「sed」只有印出第三行,
範例三那的「printf」其中有一個技巧是「xargs」,可能一時還不容易理解。
所以改用這個範例,也就是範例四來重新說明。

執行


$ printf "%s\n" Product Revision: 123456



這樣會列出


Product
Revision:
123456



「printf "%s\n" Product Revision: 123456」

改成「C語言」或是「PHP」的寫法

「printf("%s\n", "Product", "Revision:", "123456")」

這樣就比較明瞭在「Shell」使用「printf」這個指令的用法了,

「printf」是指令,
然後「"%s\n"」,「Product」,「Revision:」,「123456」
分別是「引數1 (argument 1)」「引數2 (argument 2)」「引數3 (argument 3)」「引數4 (argument 4)」。

"%s\n" 帶入「Product」變成「Product\n」
"%s\n" 帶入「Revision:」變成「Revision:\n」
"%s\n" 帶入「123456」變成「123456\n」

加上「sed」只列印出第三行

執行


$ printf "%s\n" Product Revision: 123456 | sed -n '3p'



顯示


123456



「Product Revision: 123456」改成讀檔的形式「cat ex.txt」


$ printf "%s\n" $(cat ex.txt) | sed -n '3p'



關於「$(cat ex.txt)」的用法,形式就是「$(command)」或「`command`」,請參考

* bash-handbook / Command substitution (中文版)
* info bash -n 'Command Substitution'」
* man bash 查詢「Command Substitution」。

================================================================================

## 範例5

產生一個 bash 的 function


function print_column_3 {
	echo $3
}




然後執行


print_column_3 Product Revision: 123456



顯示


123456



「Product Revision: 123456」改成讀檔的形式「cat ex.txt」


print_column_3 $(cat ex.txt)



一樣會顯示


123456



關於「$3」的用法,可以查詢關鍵字「Positional parameters」

* bash-handbook / positional-parameters (中文版)
* info bash -n 'Positional Parameters'
* man bash 查詢「Positional Parameters」


在「Bash」則是可以執行「help function」則是可以直接查詢「function」的用法

* bash-handbook / functions (中文版)
* info bash -n 'Shell Functions'
* man bash 查詢「Shell Function Definitions」

================================================================================

## 範例6

也可以產生一個「script」,檔案名稱是「print_column_3.sh」

內容如下


echo $3



只要執行下面指令,就可以產生「print_column_3.sh」


$ echo 'echo $3' > print_column_3.sh




然後執行下面指令,設定「print_column_3.sh」為可執行。


$ chmod u+x print_column_3.sh



然後執行


$ ./print_column_3.sh Product Revision: 123456



或是執行


$ sh print_column_3.sh Product Revision: 123456



或是執行


$ bash print_column_3.sh Product Revision: 123456




顯示


123456



註1:在「Ubuntu」也可以放到「~/bin」這個資料夾,就可以到處執行,
再不然就要設定「PATH」指到您要放置的資料夾,意思一樣。

觀看「~/.profile」就可以看到一段設定了。


# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
	PATH="$HOME/bin:$PATH"
fi




若要自訂「PATH」,則是建議修改在「~/.bashrc」,
或是另外寫一個檔,在「~/.bashrc」「source」該檔。

或是參考「/etc/profile」和「/etc/profile.d」的作法,拆成不同的檔案,然後「source」。


if [ -d /etc/profile.d ]; then
	for i in /etc/profile.d/*.sh; do
		if [ -r $i ]; then
			. $i
		fi
	done
	unset i
fi




註2:

「print_column_3.sh」也可以加上「Shebang」,
上面「print_column_3.sh」沒有寫「#!/usr/bin/env bash」,
若是執行「./print_column_3.sh」預設會使用「sh」來執行。

「print_column_3.sh」完整版本的內容如下


#!/usr/bin/env bash

echo $3



可以執行下面指令,產生「print_column_3.sh」這個檔案,內容如上


cat > print_column_3.sh << EOF
#!/usr/bin/env bash

echo \$3

EOF



「cat > print_column_3.sh << EOF content EOF」這個用法可以參考「Wikipidia / Here document (中文版)」。
之前我在這個「回覆#3」,有提到這個用法。


另外一種用法則是如下


echo '#!/usr/bin/env bash

echo $3
' > print_column_3.sh



或是


echo "#!/usr/bin/env bash

echo \$3
" > print_column_3.sh



================================================================================

## 範例7

延上面「範例6」的概念,改用「php」來寫 ,內容如下


#!/usr/bin/env php
<?php

echo $argv[3];



執行下面指令產生「print_column_3.php」。


cat > print_column_3.php << EOF
#!/usr/bin/env php
<?php

	echo \$argv[3];

EOF




然後執行下面指令,設定「print_column_3.php」為可執行。


$ chmod u+x print_column_3.php



然後執行


$ ./print_column_3.php Product Revision: 123456



或是執行


$ php print_column_3.php Product Revision: 123456



或是執行


$ ./print_column_3.php $(cat ex.txt)


顯示


123456




* PHP / Predefined Variables
* PHP / $argv
* PHP / $argc


或是可以寫完整一點


#!/usr/bin/env php
<?php

	if ($argc <= 3) {
		echo("引數個數必須3個以上\n");
		exit(1);
	}

	echo($argv[3] . PHP_EOL);
	exit(0);




或是


#!/usr/bin/env php
<?php

	if (!array_key_exists(3, $argv)) {
		echo("引數個數必須3個以上\n");
		exit(1);
	}

	echo($argv[3] . PHP_EOL);
	exit(0);




或是


#!/usr/bin/env php
<?php

	if (!isset($argv[3])) {
		echo("引數個數必須3個以上\n");
		exit(1);
	}

	echo($argv[3] . PHP_EOL);
	exit(0);




* PHP / array_key_exists
* PHP / isset

================================================================================

## 範例8

讀檔的部份,直接寫在「PHP」裡,拆解欄位的概念,跟上面一樣,根據「: 」來拆解。


#!/usr/bin/env php
<?php

	$content = file_get_contents(__DIR__ . '/ex.txt');
	$cols = explode(': ', trim($content));

	//var_dump($cols);

	echo $cols[1];




* PHP / file-get-contents
* PHP / explode

================================================================================

## 範例9

延續「範例6」的概念,改用「C」來寫。


#include <stdlib.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
//printf("%d\n", argc);

if (argc < 3) {
printf("引數個數必須3個以上\n");
return 1;
}

printf("%s\n", argv[3]);
return 0;
}



執行下面指令編譯


$ gcc -o print_column_3 print_column_3.c



執行下面指令



$ ./print_column_3 Product Revision: 123456



或是執行


$ ./print_column_3 $(cat ex.txt)



顯示


123456




================================================================================

延續上面「範例4」

執行


$ printf "%s\n" Product Revision: 123456



會顯示 (將一行變成多行)


Product
Revision:
123456



執行下面指令,產生「ex2.txt」這個範例檔案,內容就是上面那三行。


cat > ex2.txt < EOF
Product
Revision:
123456
EOF



或是執行


echo 'Product
Revision:
123456
' > ex2.txt




然後執行


$ cat ex2.txt



顯示


Product
Revision:
123456



執行


THE_CONTENT=$(cat ex2.txt)
echo $THE_CONTENT



就會顯示(將多行變成一行)


Product Revision: 123456



若是執行 (就會維持多行)


$ echo "$THE_CONTENT"



顯示


Product
Revision:
123456




這個可以應用在「apt-get install」,我在「這篇」有稍微提到。

先執行


cat > package.list << EOF
vim-doc
bash-doc
manpages-posix
EOF



或是先執行


echo '
vim-doc
bash-doc
manpages-posix
' > package.list




然後再執行


$ sudo apt-get install $(cat package.list)



或是執行


PACKAGE=$(cat package.list)
sudo apt-get install $PACKAGE



================================================================================

還有這裡有一個概念,需要區辨的,就是「Exit Status」,這個跟大部分程式語言「return」回來的內容,存到變數的概念不一樣。

先定義一個「function」


function get_package_list() {
	cat package.list
	return 101
}



然後執行


get_package_list



顯示


vim-doc
bash-doc
manpages-posix



然後執行


echo $?



顯示


101




再來執行


PACKAGE_LIST=$(get_package_list)
echo $?



顯示


101



再來執行


echo $PACKAGE_LIST



顯示


vim-doc bash-doc manpages-posix



懂了「Exit Status」的概念後,就可以開始學習「if」和「test」或「[」的用法了。

* help if
* help test
* help [
* type -a test
* type -a [

這篇「回覆」也有紀錄相關的議題

================================================================================

一些「Shell Script」的討論案例,我紀錄在「如何執行指令」這個索引的下方,可以一併參考。

## 一些指令的「Manpage」整理

* man echo
* man 1posix echo
* man cat
* man 1posix cat
* man cut
* man 1posix cut
* man sed
* man 1posix sed
* man 1posix awk
* man printf
* man 1posix printf
* man 3 printf
* man 3posix printf
* man xargs
* man 1posix xargs
* man sort
* man 1posix sort
* man wc
* man 1posix wc


================================================================================

導讀完畢


2016/12/26 14:58
應用擴展 工具箱
Bash scripting cheatsheet
會員五級
註冊日期:
2012/4/22 10:50
所屬群組:
已註冊使用者
等級: 37
HP : 0 / 901
MP : 671 / 29295
EXP: 6
離線
剛在「這篇」看到「Bash scripting cheatsheet (GitHub)」,

順手把連結紀錄下來。

聯想到之前還有看到「一篇」相關的文章「CLI: improved」,
還有從中看到的連結「TLDR pages (GitHub) (TLDR-clients)」,一併紀錄。


以上提供參考



2018/11/26 12:37
應用擴展 工具箱


 [無發表權] 請登錄或者註冊


可以查看帖子.
不可發帖.
不可回覆.
不可編輯自己的帖子.
不可刪除自己的帖子.
不可發起投票調查.
不可在投票調查中投票.
不可上傳附件.
不可不經審核直接發帖.