天天看點

Bash字元串處理(與Java對照) - 5.字元串輸入(讀取字元串)Bash字元串處理(與Java對照) - 5.字元串輸入(讀取字元串)

Bash字元串處理(與Java對照) - 5.字元串輸入(讀取字元串)

In Java

Scanner類:Scanner.hasNext() & Scanner.next() & Scanner.hasNextLine() & Scanner.nextLine()

JavaDoc class Scanner 寫道 A simple text scanner which can parse primitive types and strings using regular expressions.

A Scanner breaks its input into tokens using a delimiter pattern, which by default matches whitespace. The resulting tokens may then be converted into values of different types using the various next methods.

A scanning operation may block waiting for input.

The next() and hasNext() methods and their primitive-type companion methods (such as nextInt() and hasNextInt()) first skip any input that matches the delimiter pattern, and then attempt to return the next token. Both hasNext and next methods may block waiting for further input. Whether a hasNext method blocks has no connection to whether or not its associated next method will block.  

下面是關于 Scanner.hasNext() 和 Scanner.next() 的例子,用于讀取以空白分隔的辨別符。

Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
   String msg = scanner.next();
   System.out.println(msg);
}
           

下面是關于 Scanner.hasNextLine() 和 Scanner.nextLine() 的例子,用于讀取輸入資料行。

Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
   String msg = scanner.nextLine();
   System.out.println(msg);
}
           

更詳細的說明請參考:http://download.oracle.com/javase/1,5.0/docs/api/java/util/Scanner.html

Console類:System.console() & Console.readLine() & Console.readPassword()

Console類是JDK6加入的,它是對控制台的封裝。使用 System.console() 可以獲得與目前Java虛拟機關聯的控制台,如果有的話。Console.readLine可以讀取一行,Console.readPassword可以讀取密碼。

JavaDoc class Console 寫道 public final class Console

extends Object

implements Flushable

Methods to access the character-based console device, if any, associated with the current Java virtual machine.

Whether a virtual machine has a console is dependent upon the underlying platform and also upon the manner in which the virtual machine is invoked. If the virtual machine is started from an interactive command line without redirecting the standard input and output streams then its console will exist and will typically be connected to the keyboard and display from which the virtual machine was launched. If the virtual machine is started automatically, for example by a background job scheduler, then it will typically not have a console.

If this virtual machine has a console then it is represented by a unique instance of this class which can be obtained by invoking the System.console() method. If no console device is available then an invocation of that method will return null.

 String     readLine()

          Reads a single line of text from the console.

 char[]     readPassword()

          Reads a password or passphrase from the console with echoing disabled

下面是一個關于Console的示例代碼:

Console console = System.console(); // 獲得Console執行個體對象     
        if (console != null) {              // 判斷是否有控制台的使用權     
            String user = new String(console.readLine("Enter username:"));      // 讀取整行字元     
            String pwd = new String(console.readPassword("Enter passowrd:"));   // 讀取密碼,輸入時不顯示     
            console.printf("Username is: " + user + "\n");      // 顯示使用者名     
            console.printf("Password is: " + pwd + "\n");   // 顯示密碼     
        } else {     
            System.out.println("Console is unavailable.");  // 提示無控制台使用權限     
        }
           

更詳細的說明請參考:·http://download.oracle.com/javase/6/docs/api/java/io/Console.html

In Bash

從标準輸入讀取

使用read指令讀取字元串到變量中。但是,如果有反斜杠,将起到轉義的作用。\\表示一個\号,\<newline>表示續行,\<char>代表<char>本身。

格式:read VAR

格式:read -p <prompt> VAR

[[email protected] ~]# read VAR

hello world

[[email protected] ~]# echo $VAR

hello world

[[email protected] ~]# read -p "Input your number: " VAR

Input your number: 123

[[email protected] ~]# echo $VAR

123

[[email protected] ~]# read VAR

yes\tno

[[email protected] ~]# echo $VAR

yestno

[[email protected] ~]#

讀取一行文本,但是取消反斜杠的轉義作用。

格式:read -r VAR

格式:read -p <prompt> -r VAR

man bash: read 寫道 -r Backslash does not act as an escape character. The backslash is considered to be part of the

line. In particular, a backslash-newline pair may not be used as a line continuation.

[[email protected] ~]# read -r VAR

yes\tno

[[email protected] ~]# echo $VAR 

yes\tno

[[email protected] ~]#

關于read -p

此參數用于在讀取變量之前顯示提示資訊。如果輸入重定向了,就不會顯示,比如重定向從檔案中讀取。

也就是說,read -p PROMPT VAR 不等同于 echo PROMPT; read VAR 的組合。

man bash: read 寫道 -p prompt

Display prompt on standard error, without a trailing newline, before attempting to read any

input. The prompt is displayed only if input is coming from a terminal.

讀取密碼(輸入的字元不回顯)

格式:read -s PASSWORD

格式:read -p <prompt> -s PASSWORD

man bash: read 寫道 -s Silent mode. If input is coming from a terminal, characters are not echoed.  

[[email protected] ~]# echo $PASSWORD

[[email protected] ~]# read -s PASSWORD

[[email protected] ~]# echo $PASSWORD 

12345

[[email protected] ~]# read -p "Input password: " -s PASSWORD

Input password:

[[email protected] ~]# echo $PASSWORD 

54321

讀取指定數量字元

格式:read -n <nchars> VAR

格式:read -p <prompt> -n <nchars> VAR

man bash: read 寫道 -n nchars

read returns after reading nchars characters rather than waiting for a complete line of input.  

[[email protected] ~]# read -p "Input two chars: " -n 2 VAR

Input two chars: 12 [[email protected] ~]# echo $VAR

12

[[email protected] ~]#

在指定時間内讀取

格式:read -t <seconds> VAR

格式:read -p <prompt> -t <seconds> VAR

man bash: read 寫道 -t timeout

Cause read to time out and return failure if a complete line of input is not read within timeout

seconds. This option has no effect if read is not reading input from the terminal or a pipe.  

[[email protected] ~]# read -p "Input some words in 5 seconds: " -t 5 VAR

Input some words in 5 seconds: [[email protected] ~]#

從檔案中讀取

格式:read VAR <file.txt

對于read指令,可以指定-r參數,避免\轉義。

格式:read -r VAR <file.txt

錯誤:cat file.txt | read VAR    (此處read指令将會在子程序中執行,子程序無法更改父程序的變量)

[[email protected] ~]# cat input.txt

Some text here

with backslash \ here

dollar $HOME meet

[[email protected] ~]# cat input.txt | read VAR

[[email protected] ~]# echo $VAR

[[email protected] ~]# read VAR <input.txt

[[email protected] ~]# echo $VAR

Some text here

[[email protected] ~]# read VAR1 VAR2 VAR3 VAR4<input.txt

[[email protected] ~]# echo "VAR1=$VAR1 VAR2=$VAR2 VAR3=$VAR3 VAR4=$VAR4"

VAR1=Some VAR2=text VAR3=here VAR4=

[[email protected] ~]# read VAR1 VAR2<input.txt

[[email protected] ~]# echo "VAR1=$VAR1 VAR2=$VAR2"

VAR1=Some VAR2=text here

[[email protected] ~]#

上面的直接對read指令輸入重定向,隻能讀取輸入檔案中的一行。

如果需要讀取整個檔案,最好将其寫在一個代碼塊中。

Advanced Bash-Scripting Guide: Chapter 3. Special Characters {} 寫道 Block of code [curly brackets]. Also referred to as an inline group, this construct, in effect, creates an anonymous function (a function without a name). However, unlike in a "standard" function, the variables inside a code block remain visible to the remainder of the script.

The code block enclosed in braces may have I/O redirected to and from it.

Unlike a command group within (parentheses), as above, a code block enclosed by {braces} will not normally launch a subshell.

{ read LINE1; read LINE2; read LINE3; } <input.txt

注意每個read指令之後都要以分号結束。

[[email protected] ~]# { read LINE1; read LINE2; read LINE3; } <input.txt

[[email protected] ~]# echo $LINE1

Some text here

[[email protected] ~]# echo $LINE2

with backslash here

[[email protected] ~]# echo $LINE3

dollar $HOME meet

[[email protected] ~]#

上面LINE2中\ 沒有讀取出來,因為在沒有加上-r參數時,read會轉義。

現在加上-r參數來測試一下。

{ read -r LINE1; read -r LINE2; read -r LINE3; } <input.txt

[[email protected] ~]# { read -r LINE1; read -r LINE2; read -r LINE3; } <input.txt

[[email protected] ~]# echo $LINE1

Some text here

[[email protected] ~]# echo $LINE2

with backslash \ here

[[email protected] ~]# echo $LINE3

dollar $HOME meet

[[email protected] ~]#

從Here Document讀取

錯誤:read VAR <<EOF

some string

EOF

正确:{ read VAR; } <<EOF

some string

EOF

問題:為什麼寫在代碼塊中才能讀取呢?

[[email protected] ~]# read VAR <<EOF

> some string

> EOF

[[email protected] ~]# echo "$VAR"

[[email protected] ~]# { read VAR; } <<EOF

> hello

> EOF

[[email protected] ~]# echo "$VAR"        

hello

[[email protected] ~]#

從Here String讀取

read VAR <<< "some string"

read VAR <<< "$STR"

[[email protected] ~]# read VAR <<< "some string"

[[email protected] ~]# echo $VAR

some string

[[email protected] ~]#

補充:關于 cat input.txt | read VAR 的問題

先說一下我對管道線的了解:管道線兩側的指令,前一個指令的輸出(标準輸出),将作為後一個指令的輸入(标準輸入)。兩側的指令都是在子程序中執行的,都有各自獨立的位址空間,子程序會繼承(複制)父程序所有的環境變量。子Shell(subshell)是一種特殊的子程序,它會繼承(複制)父Shell的所有變量;對于非子Shell程序(外部指令),隻有環境變量會被繼承(複制)。但是,子程序一旦啟動,它所有的變量隻在它的程序空間中有效,它對變量的修改都是對自己範圍之内的變量的修改,對父程序相同名稱的變量是沒有影響的。而子程序啟動之後,它的父程序對父程序變量的修改,對子程序相同名稱的變量也是沒有影響的。

Advanced Bash-Scripting Guide: Chapter 3. Special Characters | 寫道 |

pipe. Passes the output (stdout) of a previous command to the input (stdin) of the next one, or to the shell. This is a method of chaining commands together.

A pipe, as a classic method of interprocess communication, sends the stdout of one process to the stdin of another. In a typical case, a command, such as cat or echo, pipes a stream of data to a filter, a command that transforms its input for processing.

The output of a command or commands may be piped to a script.

A pipe runs as a child process, and therefore cannot alter script variables.

variable="initial_value"

echo "new_value" | read variable

echo "variable = $variable" # variable = initial_value

[[email protected] ~]# cat input.txt

Some text here

with backslash \ here

dollar $HOME meet

[[email protected] ~]# cat input.txt | read VAR

[[email protected] ~]# echo $VAR

上面的cat input.txt的輸出将作為read VAR的輸入。

[[email protected] ~]# cat input.txt | { read VAR; echo $VAR; }

Some text here

可以看到管道線後面的子Shell中确實讀到了值。

[[email protected] ~]# echo $VAR

但父Shell中的相同變量不會改變。

[[email protected] ~]#

本文連結:http://codingstandards.iteye.com/blog/1170586   (轉載請注明出處)

傳回目錄:Java程式員的Bash實用指南系列之字元串處理(目錄) 

上節内容:Bash字元串處理(與Java對照) - 4.字元串輸出

下節内容:Bash字元串處理(與Java對照) - 6.判斷字元串是否為空(不為空)