作者 主題: 問一個許功蓋問題  (閱讀 3080 次)

0 會員 與 1 訪客 正在閱讀本文。

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17465
    • 檢視個人資料
    • http://www.study-area.org
問一個許功蓋問題
« 於: 2016-06-01 14:19 »
有勞大大審查下面script代碼:
代碼: [選擇]
#!/bin/bash
export LANG=zh_TW.Big5

in_file=1.txt

# case 1
lines=$(cat $in_file | awk -F, '{print$2,$3}')
echo "$lines"

# case 2
awk -F, '{print $2,$3}' $in_file | while read line
do
        echo $line
done
本以為兩個case的輸出會是一樣的...
但實際上會碰到許功蓋的問題:
代碼: [選擇]
[kenny@vmtest-linux tmp]$ locale
LANG=zh_TW.Big5
LC_CTYPE="zh_TW.Big5"
LC_NUMERIC="zh_TW.Big5"
LC_TIME="zh_TW.Big5"
LC_COLLATE="zh_TW.Big5"
LC_MONETARY="zh_TW.Big5"
LC_MESSAGES="zh_TW.Big5"
LC_PAPER="zh_TW.Big5"
LC_NAME="zh_TW.Big5"
LC_ADDRESS="zh_TW.Big5"
LC_TELEPHONE="zh_TW.Big5"
LC_MEASUREMENT="zh_TW.Big5"
LC_IDENTIFICATION="zh_TW.Big5"
LC_ALL=
[kenny@vmtest-linux tmp]$ file 1.txt
1.txt: ISO-8859 text
[kenny@vmtest-linux tmp]$ cat 1.txt
x1230,葉小姐,usa@xxx.com.tw,89,0,16/06/01,
x1978,許小姐,ally@xxx.com.tw,90,0,16/06/01,
x8657,陳先生,cbk@xxx.com.tw,3,0,16/06/01,
x1467,鄭成功,cck@xxx.com.tw,3,0,16/06/01,

[kenny@vmtest-linux tmp]$ ./1.sh
葉小姐 usa@xxx.com.tw
許小姐 ally@xxx.com.tw
陳先生 cbk@xxx.com.tw
鄭成功 cck@xxx.com.tw

葉小姐 usa@xxx.com.tw
酗p姐 ally@xxx.com.tw
陳先生 cbk@xxx.com.tw
鄭成?cck@xxx.com.tw

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17465
    • 檢視個人資料
    • http://www.study-area.org
Re: 問一個許功蓋問題
« 回覆 #1 於: 2016-06-01 15:08 »
應該是 read 的問題...
因為程式必須要逐行處理, 只好用awk逐行抓了:
代碼: [選擇]
for ((n=1;n<=$(cat $in_file | wc -l);n++))
do
        awk -F, "NR==$n"'{print $2,$3}' $in_file
done

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17465
    • 檢視個人資料
    • http://www.study-area.org
Re: 問一個許功蓋問題
« 回覆 #2 於: 2016-06-02 14:09 »
總算有點眉目:
應該是 \ 的問題,經過 shell 的 command line 處理,用管線傳遞到後面 read 就會消失 \ ,
但奇怪的是用 sed 's/\\/\\\\/' 好像不會抓到 \,只好用 tr 將 \ 先轉為一個確定不會出現在 string 中的符號,然後再用轉為 \\,
如此折騰一番就可以了:
代碼: [選擇]
awk -F, '{print $2,$3}' $in_file | tr '\' ',' 2>/dev/null | sed 's/,/\\\\/g' | while read line

Yamaka

  • 俺是博士!
  • *****
  • 文章數: 4913
    • 檢視個人資料
    • http://www.ecmagic.com
Re: 問一個許功蓋問題
« 回覆 #3 於: 2016-06-02 14:30 »
怎不先將資料轉 utf8 再處理?

netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17465
    • 檢視個人資料
    • http://www.study-area.org
Re: 問一個許功蓋問題
« 回覆 #4 於: 2016-06-02 14:57 »
怎不先將資料轉 utf8 再處理?
也是可以,但處理完還要再轉回Big5... Orz

Yamaka

  • 俺是博士!
  • *****
  • 文章數: 4913
    • 檢視個人資料
    • http://www.ecmagic.com
Re: 問一個許功蓋問題
« 回覆 #5 於: 2016-06-02 15:12 »
建議用 cconv 來轉換啦

引用
$ local
LANG=en_US.UTF-8
LANGUAGE=en_US
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC=en_US.UTF-8
LC_TIME=en_US.UTF-8
LC_COLLATE="en_US.UTF-8"
LC_MONETARY=en_US.UTF-8
LC_MESSAGES="en_US.UTF-8"
LC_PAPER=en_US.UTF-8
LC_NAME=en_US.UTF-8
LC_ADDRESS=en_US.UTF-8
LC_TELEPHONE=en_US.UTF-8
LC_MEASUREMENT=en_US.UTF-8
LC_IDENTIFICATION=en_US.UTF-8
LC_ALL=

$ file f1.txt
f1.txt: ISO-8859 text

$ cat f1.txt|cconv -f BIG5 -t UTF8
x1230,葉小姐,usa@xxx.com.tw,89,0,16/06/01,
x1978,許小姐,ally@xxx.com.tw,90,0,16/06/01,
x8657,陳先生,cbk@xxx.com.tw,3,0,16/06/01,
x1467,鄭成功,cck@xxx.com.tw,3,0,16/06/01,


最後只要 cconv -f  -t 對調再跑一次就轉回 big5

我自己用 cconv 轉過不少資料
速度夠快,到目前還沒出過問題 ^___^

dark

  • 俺是博士!
  • *****
  • 文章數: 1581
    • 檢視個人資料
Re: 問一個許功蓋問題
« 回覆 #6 於: 2016-06-03 11:27 »
滿幸運以前沒遇到這樣問題
因為小弟的資料都是數字吧 ...

# read -h
-bash: read: -h: invalid option
read: usage: read [-ers] [-u fd] [-t timeout] [-p prompt] [-a array] [-n nchars] [-d delim] [name ...]

剛剛由於好奇 -ers 都沒用過 , 試了一下這 3 種
echo 許功蓋 | while read -r x;do echo $x;done
原來 -r 是答案

把 man 拿去翻譯才知道
Backslash  does  not  act  as an escape character.  The backslash is   considered to be part of the line.  In particular, a  backslash-new- line pair may not be used as a line continuation.
反斜杠不作為轉義字符。反斜杠認為是行的一部分。特別是一個反斜杠新行對可以不使用作為續行。

雖然第二句可能意思是換行無效 , 但換行是 echo 的事了


netman

  • 管理員
  • 俺是博士!
  • *****
  • 文章數: 17465
    • 檢視個人資料
    • http://www.study-area.org
Re: 問一個許功蓋問題
« 回覆 #7 於: 2016-06-03 18:57 »
感謝 Dark 兄!
原來還有這麼簡單的解法~~ 果然加個 -r 就可以了。
又學到一招,感謝!