2025-02-10

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() 的例子,用於讀取以空白分隔的標識符。
Java代碼 
Scanner scanner = new Scanner(System.in); 
while (scanner.hasNext()) { 
   String msg = scanner.next(); 
   System.out.println(msg); 

 
下面是關於 Scanner.hasNextLine() 和 Scanner.nextLine() 的例子,用於讀取輸入數據行。
Java代碼 
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的示例代碼:
 
Java代碼 
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
 
[root@node56 ~]# read VAR
hello world
[root@node56 ~]# echo $VAR
hello world
[root@node56 ~]# read -p "Input your number: " VAR
Input your number: 123
[root@node56 ~]# echo $VAR
123
[root@node56 ~]# read VAR
yes\tno
[root@node56 ~]# echo $VAR
yestno
[root@node56 ~]#
 
 
讀取一行文本,但是取消反斜杠的轉義作用。
格式: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.
 
[root@node56 ~]# read -r VAR
yes\tno
[root@node56 ~]# echo $VAR 
yes\tno
[root@node56 ~]#
 
關於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.
 
[root@node56 ~]# echo $PASSWORD

[root@node56 ~]# read -s PASSWORD
[root@node56 ~]# echo $PASSWORD 
12345
[root@node56 ~]# read -p "Input password: " -s PASSWORD
Input password:
[root@node56 ~]# 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.
 
[root@node56 ~]# read -p "Input two chars: " -n 2 VAR
Input two chars: 12 [root@node56 ~]# echo $VAR
12
[root@node56 ~]#
 
在指定時間內讀取
格式: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.
 
[root@node56 ~]# read -p "Input some words in 5 seconds: " -t 5 VAR
Input some words in 5 seconds: [root@node56 ~]#
 
從文件中讀取
格式:read VAR <file.txt
對於read命令,可以指定-r參數,避免\轉義。
格式:read -r VAR <file.txt
錯誤:cat file.txt | read VAR    (此處read命令將會在子進程中執行,子進程無法更改父進程的變量)
 
[root@web ~]# cat input.txt
Some text here
with backslash \ here
dollar $HOME meet

[root@web ~]# cat input.txt | read VAR
[root@web ~]# echo $VAR

[root@web ~]# read VAR <input.txt
[root@web ~]# echo $VAR
Some text here
[root@web ~]# read VAR1 VAR2 VAR3 VAR4<input.txt
[root@web ~]# echo "VAR1=$VAR1 VAR2=$VAR2 VAR3=$VAR3 VAR4=$VAR4"
VAR1=Some VAR2=text VAR3=here VAR4=
[root@web ~]# read VAR1 VAR2<input.txt
[root@web ~]# echo "VAR1=$VAR1 VAR2=$VAR2"
VAR1=Some VAR2=text here
[root@web ~]#
上面的直接對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命令之後都要以分號結束。
 
[root@web ~]# { read LINE1; read LINE2; read LINE3; } <input.txt
[root@web ~]# echo $LINE1
Some text here
[root@web ~]# echo $LINE2
with backslash here
[root@web ~]# echo $LINE3
dollar $HOME meet
[root@web ~]#
上面LINE2中\ 沒有讀取出來,因為在沒有加上-r參數時,read會轉義。
 
現在加上-r參數來測試一下。
{ read -r LINE1; read -r LINE2; read -r LINE3; } <input.txt
 
[root@web ~]# { read -r LINE1; read -r LINE2; read -r LINE3; } <input.txt
[root@web ~]# echo $LINE1
Some text here
[root@web ~]# echo $LINE2
with backslash \ here
[root@web ~]# echo $LINE3
dollar $HOME meet
[root@web ~]#
 
從Here Document讀取
錯誤:read VAR <<EOF
some string
EOF
正確:{ read VAR; } <<EOF
some string
EOF
問題:為什麼寫在代碼塊中才能讀取呢?
 
[root@web ~]# read VAR <<EOF
> some string
> EOF
[root@web ~]# echo "$VAR"

[root@web ~]# { read VAR; } <<EOF
> hello
> EOF
[root@web ~]# echo "$VAR"        
hello
[root@web ~]#
 
從Here String讀取
read VAR <<< "some string"
read VAR <<< "$STR"
 
[root@web ~]# read VAR <<< "some string"
[root@web ~]# echo $VAR
some string
[root@web ~]#
 
 
補充:關於 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
 
[root@web ~]# cat input.txt
Some text here
with backslash \ here
dollar $HOME meet

[root@web ~]# cat input.txt | read VAR
[root@web ~]# echo $VAR
 
上面的cat input.txt的輸出將作為read VAR的輸入。
[root@web ~]# cat input.txt | { read VAR; echo $VAR; }
Some text here
可以看到管道線後面的子Shell中確實讀到瞭值。
[root@web ~]# echo $VAR
 
但父Shell中的相同變量不會改變。
[root@web ~]#

作者“Bash @ Linux”
 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *