輸出 / 入重新導向 (Redirection)

基本上,Linux 將標準 I/O分為三種,分別是:標準輸入 (stdin, Standard Input)、 標準輸出 (stdout, Standard Output) 及標準錯誤輸出 (stderr, Standard Error)。標準輸入就是指標準輸入設備鍵盤的輸入,或是一般指令後面所加的參數,例如:ls dir1,dir1 就是標準輸入。標準輸出則是指輸出到螢幕,例如:ls dir1 顯示在螢幕上的結果。標準錯誤輸出是指指令執行錯誤時,產生的錯誤訊息,例如:ls dir1結果沒有 dir1 這個目錄時,顯示在螢幕上的錯誤訊息。

輸出導向 :>

 

# ls dir1 > file1 執行結果會儲存到檔案 file1 中,而不是顯示在螢幕上
# cat file2 file3 > file4 將 file2 與 file3 兩個檔案合併後存到檔案 file4
# cat > file5 可以在鍵盤上輸入資料,直到按下 Ctrl+d 結束,所有輸入的資料即為新建檔案 file5 的內容
# exefile > /dev/null 執行檔 exefile 的執行結果將會消失不見

 

※ 上述輸出導向指令在執行之前,會先將右邊參數所指的檔案 (e.g., file1, file4 etc.) 內容清空

附加輸出導向 :>>

# cat file2 >> file1 將 file2 的內容附加到檔案 file1 的後面

輸入導向 :<

# cat <> 結果與「cat file1」相同
# mail user1 <> 將檔案 file2 的內容直接寄給使用者 user1

附加輸入導向 :<<

附加輸入導向「<< string」是指輸入會一直持續到遇到字串 "string" 為止,例如:

cat > file1 <<>

> This is a simple input test!

> You can do the input until eof appear.

> eof

 

錯誤輸出導向 :2>

 

# ls dir1 2> err.out 執行錯誤訊息將會存到檔案 err.out
# ls dir1 > file1 2>&1 將正確執行結果與錯誤輸出都寫入同一檔案 file1
# ls dir1 &> file1 同時將標準輸出與標準錯誤輸出導向到檔案 file1
# ls dir1 >& file1 同時將標準輸出與標準錯誤輸出導向到檔案 file1

管線 (pipe)|

管線的功用就是將程式的輸出引導為另一個程式的輸入,例如:

# ls -l dir1 | more 將執行結果一頁一頁的顯示

雙向重導向tee

last | tee ~/last.list 顯示所有登入過系統的使用者清單,並儲存一份至檔案 last.list

關於 sscanf

一般使用

char str[512] = {0};

sscanf("123456 ", "%s", str);

printf("str=%s\n", str);


取出指定長度字串,例如:取4個字元

sscanf("123456 ", "%4s", str);

printf("str=%s\n", str);


取出到指字字元為止的字串,例如:取出遇到空格為止前的字串

sscanf("123456 abcdedf", "%[^ ]", str);

printf("str=%s\n", str);


取出包含指定字元的字串,例如:取出包含1到9與小寫字母的字串


sscanf("123456abcdedfBCDEF", "%[1-9a-z]", str);

printf("str=%s\n", str);


取出到指字字元為止的字串,例如:取出遇到大寫字母為止的字串


sscanf("123456abcdedfBCDEF", "%[^A-Z]", str);

printf("str=%s\n", str);


字串連結指令 strcat()、strncat()

(1)strcat()

1.指令說明:

原型為:
char *strcat(char *strDestination, const char *strSource);

參數說明:
strDestination: 字串連接後,要存放的位置(目的地的指標)
strSource: 字串連接的來源位置(來源的指標)

輸出:
執行完,後會將strDestination的位置作輸出

2.使用範例:
ex.
void main()
{
char szDestination[10] = "0123";
char szSource[] = "4567";

printf("執行strcat()指令前\n");
printf("szDestination=%s\n", szDestination);

// 將szSource字串連接到szDestination字串之後
strcat(szDestination, szSource);

printf("執行strcat()指令後\n");
printf("szDestination=%s\n", szDestination);

system("pause");
}

輸出:

執行strcat()指令前
szDestination=0123
執行strcat()指令後
szDestination=01234567

3.實作:

// 實作strcat指令
// strDestination ==> 目的字串指標
// strSource ==> 來源字串指標
char* MyStrcat(char* strDestination, const char* strSource)
{
int nLen = 0;
int nCount = 0;

// 這一個地方,是防止strDestination或strSource是指向NULL,所作的錯誤偵測
if(strDestination == NULL || strSource == NULL)
{
return NULL;
}

// 計算要在strDestination陣列中,開始連接strSource字串的位置
nLen = strlen(strDestination);

// 若來源字串指標未讀到字串結尾'\0'
while(*(strSource + nCount) != '\0')
{
// 將目前strSource + nCount所指的字元,放到strDestination中(目的字串指標)
*(strDestination + nLen + nCount) = *(strSource + nCount);

// 指向下一個要連接的位置
nCount++;
}

// 在strDestination的中,放入字串結尾'\0'
*(strDestination + nLen + nCount) = '\0';

// 回傳目的字串指標
return strDestination;
}

ps:
strncat()指令在執行時,並無法考慮到目的指標陣列,是否有足夠的空間來存放連接後的字串
因此很容易讓陣列爆掉(Buffer Overow),因此建議使用strncat()來取代strcat()

MSDN對strcat指令的說明



(2)strncat()

1.指令說明:

原型為:
char *strncat(char *strDest, const char *strSource, size_t count);

參數說明:
strDest: 字串複製後要存放的位置(目的地的指標)
strSource: 字串複製的來源位置(來源的指標)
count:最多可從strSource取得多少字元,來連接到strDest

輸出:
執行完,後會將strDest的位置作輸出

2.使用範例:
ex.
void main()
{
// 強列建議在宣告szDestination前,要先作陣列初使化或在字串陣列的最後一個字元
// 放入'\0',防止szSource的字元數,比szDestination還大時
// 在執行完strncat指令後,會因找不到字串結尾,而引起不必要的錯誤
char szDestination[10] = "0123456";
char szSource[] = "789ABCDEF";
int nCount = 0;

printf("執行strncat()指令前\n");
printf("szDestination=%s\n", szDestination);

// sizeof(szDestination) ==> 計算szDestination陣列大小
// strlen(szDestination) ==> 計算szDestination陣列中,存放的字元數
// sizeof(szDestination) - strlen(szDestination) ==> szDestination陣列中,剩少多少空間,可存放字元
nCount = sizeof(szDestination) - strlen(szDestination);

// 將szSource字串連接到szDestination字串之後
// nCount - 1中的 -1是為了要預留字串結尾'\0'的空間
strncat(szDestination, szSource, nCount - 1);

printf("執行strncat()指令後\n");
printf("szDestination=%s\n", szDestination);

system("pause");
}


輸出:

執行strncat()指令前
szDestination=0123456
執行strncat()指令後
szDestination=012345678

3.實作:

// 實作strncat指令
// strDestination ==> 目的字串指標
// strSource ==> 來源字串指標
char* MyStrncat(char* strDestination, const char* strSource, unsigned int count)
{
int nLen = 0;
int nCount = 0;

// 這一個地方,是防止strDestination或strSource是指向NULL,所作的錯誤偵測
if(strDestination == NULL || strSource == NULL)
{
return NULL;
}

// 計算要在strDestination陣列中,開始連接strSource字串的位置
nLen = strlen(strDestination);

// 若來源字串指標未讀到字串結尾'\0'
// 並且所連接的字元數,不得大於count
while(*(strSource + nCount) != '\0' && nCount < count)
{
// 將目前strSource + nCount所指的字元,放到strDestination中(目的字串指標)
*(strDestination + nLen + nCount) = *(strSource + nCount);

// 指向下一個要連接的位置
nCount++;
}

if(*(strSource + nCount) == '\0')
{
// 在strDestination的中,放入字串結尾'\0'
*(strDestination + nLen + nCount) = '\0';
}

// 回傳目的字串指標
return strDestination;
}

MSDN對strncat()指令的說明

Blogger Templates by Blog Forum