[Shell Script]字串與檔案處理的小技巧大全(更新2016/05/27)

  • 65746
  • 0
  • 2016-05-27

摘要:[Shell Script]字串與檔案處理的小技巧大全(也許會不斷新增)

SV是使用bash shell, 也就是開頭#!/bin/sh的那種~

因為處理檔案有太多東西是會用到但是總在網上找個半天(因為原本的方法也很難找到是在哪寫過),

所以以後就有專門給自己看得指令大全!

要是真的那個文件發生意外,至少還有這裡做紀錄~

 

1.去除第一個字(去除前n個字就多加.)

echo $string | sed 's/^.//'

 

2.字串取代(因為檔案中的字串取代比較常見,僅記錄純字串的)

echo $string | sed -r 's/str1/str2/g'

 

3.找字串存在檔案中的那一行

grep -n $query $file

 

不過會跑出$query,

像是$query=123

就會跑出:

12:123

表示123在檔案的第12行,所以記得要 | awk -F':' '{print $1}'

 

4.從檔案某一行取代整串字

聽起來很簡單,但是SV用很笨的方法,剛好搭配上述的第三個小技巧,中間會有兩個暫存檔:

oldLine=$(grep -n $query $file | awk -F':' '{print $1}')
sed $oldLine"i$newKey" "$file" > "$file"".tmps2"
// 會將資料插入特定的行
nextLine=`expr $oldLine + 1`
sed -e $nextLine'd' "$file"".tmps2" > "$file"".tmps"
// 接著刪除某一行的下一行(因為插入的是新資料,舊資料還在下一行)
rm "$file"".tmps2"
//刪除暫存的檔案
mv "$file"".tmps" "$file"
//將最後的暫存檔案取代成原本的檔案

 

5.去掉字串的最後一個字

這個應用是因為,常常有for迴圈做字串累加,

比方1,2,3,4,5,......,n,

結果最後那個n懶得做計數去除(比方判斷是最後一筆時就不累加,),

因此才會用到這方法:

string=${string%?}

 

6.計算query在檔案中出現的次數

$query是你要找的字串

cat $file | grep -o "$query" | wc -l

記得有特殊字元要加\

像是:

 

cat $file | grep -o "\[$query]" | wc -l

以上主要是因為左中括號[要被escape掉。(想找到的型式是[123])

 

7.刪除檔案中的第n~m行

        #刪除檔案中的3~18行
        startLine=3
	endLine=18
	sed -e "$startLine,$endLine"d $file > $file.tmp
	mv -f $file.tmp $file

以上幾乎都是網路上找到的方法,很感謝stackoverflow的大大們~

 

另外,我一直困擾著一行一行讀取檔案的方法,

通常會用while:

while read line; do
        echo $line
done < $file

或者for:

for line in $(cat $file)
do
      echo $line
done

不過for的風險在於他更趨近於用空格來讀檔~

我試過的最後,檔案內容一長(也不用上萬行,僅需10幾行),

若是要從網頁讀檔(用post或get的httprequest抓shell script結果),

都會很久(因為他每跑一個迴圈就是一段時間,1筆1秒,10筆就要跑10秒)......

假設你的內容很簡單、有規律(比方日期+資訊→2014/11/20 第一筆資料),

我個人會傾向於在shell script抓資料時直接用cat。

你會納悶,那麼我從client端抓資料時,即使檔案有\n,使用者介面就是不領情,還是給他連起來呀!

那就是重點了!字串剖析的部分應該由client端(像是javascript)來做會比較快速!

但如果你的資料真的很醜、沒有規則......那這資料還有意義嗎!!!(開玩笑地)

(我想就算是server端要剖析應該也不容易吧......)

那你就只好另請高明了~

最後,雖然很簡單,以上的方法如果你要弄成變數,

只要這樣(以第三條為例):

var=$(grep -n $query $file | awk -F':' '{print $1}')

這樣變數var就會等於你用字串搜尋檔案的那一行號囉~

也就是用$()包起你的指令再丟給變數~

8.刪除某個檔案的某行

sed -e "$line"d "$file" > "$file"".tmp"
mv "$file"".tmp" "$file"

9.插入到某檔案的特定行

if n == specific line
sed "ni$new" "$file" > "$file"".tmp"
mv "$file"".tmp" "$file"

10.乘法

`expr 1 + 4 \* $number + 1`

11.刪除檔案的最後一行

cp $file $file.tmp
sed '$ d' $file.tmp > $file
rm -f $file.tmp

12.取代檔案中的字串

sed -i "s/$old/$new/g" "$file"

13.讀取檔案前n筆

sed -n 1,np $file

14.一行一行讀檔(用while)並找出想要的行數

countTest=0
while read line         
do
	countTest=`expr $countTest + 1`
	if [ "$line" == "$query" ]; then
		countPage=$countTest
	fi
done <${file}

15.排程-跑php執行檔案

先打開排程編輯軟體

crontab -e

接著依要求撰寫。

例如:每10秒執行一次:

* * * * * /usr/bin/php /var/www/html/Test/test.php
* * * * * sleep 10; /usr/bin/php /var/www/html/Test/test.php
* * * * * sleep 20; /usr/bin/php /var/www/html/Test/test.php
* * * * * sleep 30; /usr/bin/php /var/www/html/Test/test.php
* * * * * sleep 40; /usr/bin/php /var/www/html/Test/test.php
* * * * * sleep 50; /usr/bin/php /var/www/html/Test/test.php

16.編輯大檔案的作法(技巧):

用字串比對、行數或任何方式抓到需要編輯的部分到smallpart檔案,
在smallpart編輯完後,
合併成原本的檔案(因此檔案未合併前有part1,smallpart,part2).tmp
mv file.tmp file
 

17. 傳檔案至遠端

wget -P 目的資料夾 檔案

18.從遠端抓檔案並覆蓋原本檔案 

wget -O 路徑與檔名

19. 取得後n碼

test="1234567890"
result=$(echo $test | grep -o '...$')
結果(後3碼):
890

20.取得字串中的第幾個字

result=`expr substr "$test" n 1`
test="123456"
result=`expr substr "$test" 2 1`
結果 2

21.使用動態變數

方法一:

count=2
let n$count=123
test=n$count
echo ${!test}
結果123(形同echo出n2,而n2=123)

方法二:

count=3
declare "n"$count=456
echo $n3
結果456(用declare產生變數)

22. 刪除檔案的^M

有時候從Windows系統將檔案copy到Linux系統時,檔案會有^M

所以這樣刪除:

sed -i -e 's/.$//' $FILE

$FILE是檔案名稱(或加路徑的檔案名稱)

23. 資料夾中找出現特殊字串的檔案

grep -rnw '/dir/' -e "query"