Linux--Shell指令碼逐行讀文字處理並curl傳送post請求json格式等問題
問題:Shell指令碼逐行讀取文字,字串分割,Curl傳送Post請求Json格式等相關問題
在linux中使用curl傳送一個post請求時,帶有json的資料,在傳送時發現json中的變數沒有解析出來:
curl -d '{"Pin": "${line}"}' -H"tp-app-id:publicclouds" -H"tp-sig:e26fe2c1924d9b4d86d19145434e3a5e" -H"tp-ts:14x6204133" -H"Content-Type:application/json" http://localhost:8070/alarm/activityPush
錯誤提示:
{"Code":1, "Msg":"invalid character '$' looking for beginning of value"}
這與json傳資料的單引號 ('') 有關,shell指令碼中('')內的字串都只能原樣輸出。
解決方案,在資料上再加上單引號('') :
curl -d '{"Pin": "'${line}'"}' -H"tp-app-id:publicclouds" -H"tp-sig:e26fe2c1924d9b4d86d19145434e3a5e" -H"tp-ts:14x6204133" -H"Content-Type:application/json" http://localhost:8070/alarm/activityPush
相關栗子:
逐行讀取文字文件中的資料,拆分存入陣列,傳入json進行curl請求:
#!/bin/bash echo "output" > 2.txt cat test.txt | while read line do echo "File:${line}" echo ${line} >> 2.txt #array=(${line//,/ }) #replace , to " " #for var in ${array[@]} #do # echo $var >>2.txt #done old_ifs="$IFS" IFS="," array=($line) IFS="$old_ifs" i=0 while [ $i -lt ${#array[@]} ] do echo ${array[i]} let i++ done curl -d '{"Pin": "'${line}'"}' -H"tp-app-id:publiccloud" -H"tp-sig:e26fe2c1924d9b4d86d19145434e3a1e" -H"tp-ts:1456204133" -H"Content-Type:application/json" http://localhost:8070/alarm/activityPush >> 2.txt done
讀取文件
提示錯誤資訊:
invalid character '\r' in string literal"
由於在shell處理了windows裡的字元檔案,導致本該輸出成兩行的字串變成了一行,而第一行行首的一些字元被第二行覆蓋了
這是由於windows和linux下的/r ^M 字元的區別導致,可以將異常字元都篩選掉再進行輸出:如sed 's/[^0-9,.:A-Za-z]//g'把不符合規則的字元過濾掉
Unix體系裡,每行結尾只有“<換行>”,即“\n”;Windows體系裡面,每行結尾是“<換行><回 車>”,即“\n\r”。一個直接結果是,Unix體系下的檔案在Windows裡開啟的話,所有文字會變成一行;而Windows裡的檔案在Unix下開啟的話,在每行的結尾可能會多出一個^M符號。
好了,所以我的題目就出在被處理懲罰的檔案的每行末尾都有^M符號,而這凡是是看不出來的。可以用"cat -A test.file"號令檢視。是以當我想在行尾新增字元的時辰,它老是新增在行首且會覆蓋掉本來行首的字元。
要把檔案轉換一下,有兩種辦法:
- 命令列:dos2unix test.file
- 去掉"\r" ,用號令sed -i ""s/\r//"" test.file
shell指令碼逐行讀取
經常會對文體檔案進行逐行處理,在Shell裡面如何獲取每行資料,然後處理該行資料,最後讀取下一行資料,迴圈處理.有多種解決方法如下:
1.通過read命令完成.
read命令接收標準輸入,或其他檔案描述符的輸入,得到輸入後,read命令將資料放入一個標準變數中.
利用read讀取檔案時,每次呼叫read命令都會讀取檔案中的"一行"文字.
當檔案沒有可讀的行時,read命令將以非零狀態退出.
cat data.dat | while read line
do
echo "File:${line}"
done
while read line
do
echo "File:${line}"
done < data.dat
2.使用for var in file 命令完成
for var in file 表示變數var在file中迴圈取值.取值的分隔符由$IFS確定.
for line in $(cat data.dat)
do
echo "File:${line}"
done
for line in `cat data.dat`
do
echo "File:${line}"
done
如果輸入文字每行中沒有空格,則line在輸入文字中按換行符分隔符迴圈取值.
如果輸入文字中包括空格或製表符,則不是換行讀取,line在輸入文字中按空格分隔符或製表符或換行符特環取值.可以通過把IFS設定為換行符來達到逐行讀取的功能.
IFS的預設值為:空白(包括:空格,製表符,換行符).
3.使用awk命令完成
awk是一種優良的文字處理工具,提供了極其強大的功能.
利用awk讀取檔案中的每行資料,並且可以對每行資料做一些處理,還可以單獨處理每行資料裡的每列資料.
cat data.dat | awk '{print $0}'
cat data.dat | awk 'for(i=2;i<NF;i++) {printf $i} printf "\n"}'
第1行程式碼輸出data.dat裡的每行資料,第2程式碼輸出每行中從第2列之後的資料.
如果是單純的資料或文字檔案的按行讀取和顯示的話,使用awk命令比較方便.
分割字串
- shell變數的字串替換直接分割
- 自定義IFS變數, 改變分隔符, 對字串進行切分
1.用string來替換parameter變數中所有匹配的pattern
${parameter//pattern/string}
#array=(${line//,/ }) #replace , to " "
#for var in ${array[@]}
#do
# echo $var >>2.txt
#done
2.當 shell 處理"命令替換"和"引數替換"時,shell 根據 IFS 的值,預設是 space, tab, newline 來拆解讀入的變數,然後對特殊字元進行處理,最後重新組合賦值給該變數。
檢視變數 IFS 的值:
$ echo $IFS
$ echo "$IFS" | od -b
0000000 040 011 012 012
0000004
直接輸出IFS是看不到的,把它轉化為二進位制就可以看到了,"040"是空格,"011"是Tab,"012"是換行符"\n" 。最後一個 012 是因為 echo 預設是會換行的。
old_ifs="$IFS"
IFS=","
array=($line)
IFS="$old_ifs"
i=0
while [ $i -lt ${#array[@]} ]
do
echo ${array[i]}
let i++
done
End