2016-12-31 33 views
4

所以,我有以下問題,但我的問題是更通用的 - 怎麼看的由bash的變量引用的內存確切的內容理解爲什麼他們不匹配:查看bash變量的確切內容? (hexdump都沒有幫助)

# [[ $c1 == $c ]] || echo nope 
nope 
# [[ $c1 == "bkup dt" ]] || echo nope 
# [[ $c == "bkup dt" ]] || echo nope 
nope 
# hexdump -C <<<$c 
00000000 62 6b 75 70 20 64 74 0a       |bkup dt.| 
00000008 
# hexdump -C <<<$c1 
00000000 62 6b 75 70 20 64 74 0a       |bkup dt.| 
00000008 
# [ "$c1" = "$c" ] || echo nope 
nope 
# [ ! "$c1" = "$c" ] || echo nope 

還是它看起來像一個錯誤?我可以重複問題:

$ cd /tmp 
$ mkdir aaa 
$ echo 2 > aaa/1 
$ echo 2 > aaa/2 
$ c=$(ls -A aaa) 
$ [[ $c == $(echo $c) ]] || echo not equal 
not equal 
$ hexdump -C <<<$c 
00000000 31 20 32 0a          |1 2.| 
00000004 
$ hexdump -C <<<$(echo $c) 
00000000 31 20 32 0a          |1 2.| 
00000004 
$ c1="1 2" 
$ [[ $c1 == $(echo $c1) ]] || echo not equal 
$ [[ $c1 == $(echo $c) ]] || echo not equal 
$ [[ $c1 == $c ]] || echo not equal 
not equal 
+0

您正在看到確切的con變量的帳篷;你只是得到了由這個字符串引起的*額外*換行符('0a')。 'printf'%s'「$ c」|如果你不想簡單地忽略它,hexdump -C'會忽略它。 – chepner

回答

10

檢查變量的內容最好的辦法是用declare -p

$ c="1 2" 
$ declare -p c 
declare -- c="1 2" 

請注意,你的測試是錯誤的,因爲你錯過了引號你的變量擴展!

看:

$ c="1 2" # with two spaces 
$ declare -p c 
declare -- c="1 2" 
$ echo $c 
1 2 
$ echo "$c" 
1 2 
$ d=$(echo $c) 
$ declare -p d 
1 2 

您必須引用的每一個變量擴展,除非你真的想有字的拆分和路徑擴展應用到他們!(通常情況下,你肯定不希望發生這種情況)。

即使你hexdump戰略需要報價:

$ c="1 2" # two spaces 
$ hexdump <<< $c 
00000000 31 20 32 0a          |1 2.| 
00000004 
$ hexdump <<< "$c" 
00000000 31 20 20 32 0a         |1 2.| 
00000005 

什麼您遇到的正是這一點:

$ mkdir aaa; touch aaa/{1,2} 
$ c=$(ls -A aaa) 
$ declare -p c 
declare -- c="1 
2" 
$ # see? there's a new line between the files. 
$ echo $c 
1 2 
$ echo "$c" 
1 
2 
$ # Use quotes! 

有時declare -p不會很放映空間正常。在這種情況下,你可以使用printf像這樣:

$ c=$' \n' 
$ declare -p c 
declare -- c="  
" 
$ # there are spaces, but you can't see them 
$ printf '%q\n' "$c" 
$' \n' 

的申報策略也不錯,你可以檢查數組和功能太:

$ a=(one two "three four") 
$ declare -p a 
declare -a a='([0]="one" [1]="two" [2]="three four")' 
$ declare -A h=([one]=1 [two]=2) 
$ declare -p h 
declare -A h='([one]="1" [two]="2")' 
$ f() { echo hello; } > somewhere > >(over the rainbow) 
$ declare -pf f 
f() 
{ 
    echo hello 
} > somewhere 2> >(over the rainbow) 
$ # You need also the -f switch to target functions 

您還可以訪問的標誌變量:

$ declare -litux hello=world 
$ declare -p hello 
declare -itx hello="0" 
$ # Have fun! 
+0

是的,這正好回答了這個問題,不知道我怎麼能通過我自己找到答案:) – noonex

+0

請注意,<<<'的參數*記錄*爲不經歷單詞拆分,但實際上並非如此直到'bash' 4.4。 – chepner

+0

使用'c ='a b'',hd <<< $ a'和'hd <<<「$ a」'在當前bash版本4.4中產生相同的輸出。所以,這沒有任何幫助。 – sorontar

0

您看不到變量的確切內容,因爲您要求bash修改它。最基本的效果是在此命令:

$ echo hello # world 
hello 

$ echo "hello # world" 
hello # world 

引用防止shell解釋特殊字符#爲註釋開始字符,並且因此它被打印。

read more here

打印可變的確切內容,唯一正確的方法是引用它。

a='a \b 
|c  d' 

上面,var a正在得到一個確切的字符串,因爲它是單引號。

$ echo "$a" 
a \b 
|c  d 

以上,var a的值由於雙引號而被完全重現。

只要你沒有引用一個變量擴展$a,你得到的東西別人:

$ echo $a 
a \b |c d 

這是任何shell的一個很基本的要求:引用。
並且有單引號,雙引號和反斜槓引用。


在你的情況下,重現你所看到的,在瓦爾不是真正平等的,它們分別是:

$ c='bkup dt 
' 

$ c1='bkup dt' 

也就是說,C包含額外的換行符相比C1 。

讓我們重複您的命令,但要正確引用以查看每個var的真實內容(請理解,在[[…]]內部大部分時間內可以使用未引用的變量)。

$ [[ $c1 == $c ]] || echo nope 
nope 

變量不相等。

$ [[ $c1 == "bkup dt" ]] || echo nope 

可變c1正好等於bkup dt(無輸出)。

$ [[ $c == "bkup dt" ]] || echo nope 
nope 

不,c不完全是「bkup dt」(它有一個額外的新行)。

$ hexdump -C <<<"$c" 
00000000 62 6b 75 70 20 64 74 0a 0a      |bkup dt..| 
00000009 

注換行符末,現在所引用的變量正確地再現與從<<<添加的新行其內部值。與$c1比較。

$ hexdump -C <<<"$c1" 
00000000 62 6b 75 70 20 64 74 0a       |bkup dt.| 
00000009 

只有一個換行符。

也許更好的方法將是使用:

$ printf '%s' "$c" | od -vAn -tx1c 
62 6b 75 70 20 64 74 0a 
    b k u p  d t \n 

這裏,變數內換行清楚地顯示。

變量$c1不表明:

$ printf '%s' "$c1" | od -vAn -tx1c 
62 6b 75 70 20 64 74 
    b k u p  d t 

命令聲明也可以用於:

$ declare -p c 
declare -- c="bkup dt 
" 

$ declare -p c1 
declare -- c1="bkup dt" 

至於貓,sed和其他一些人:

$ echo "$c" | cat -vET 
bkup dt$ 
$ 

$ echo "$c1" | cat -vET 
bkup dt$ 

$ echo "$c" | sed -n l 
bkup dt$ 
$ 

$ echo "$c1" | sed -n l 
bkup dt$ 

如果您引用變量擴展並知道新行的外觀如何。


你的第二個例子也有一個新的行問題。

$ cd /tmp; mkdir aaa; echo 2 > aaa/1; echo 2 > aaa/2 
$ c=$(ls -A aaa) 
$ echo $c | od -vAn -tx1c 
    31 20 32 0a 
    1  2 \n 

在這種情況下,c似乎有一個空間,但它真的是:​​

$ echo "$c" | od -vAn -tx1c 
    31 0a 32 0a 
    1 \n 2 \n 

一個換行符

因此,迴音也沒有(爲一對夫婦缺少引號,都需要):

$ echo $(echo $c) | odc 
    31 20 32 0a 
    1  2 \n 

$ echo "$(echo "$c")" | odc 
    31 0a 32 0a 
    1 \n 2 \n