我有一個包含各種資料(日期、時間、速度、與前面的距離、與后面的距離)的檔案,檔案看起來像這樣,只是有更多行:
2003.09.23.,05:05:21:64,134,177,101
2009.03.10.,17:46:17:81,57,102,57
2018.01.05.,00:30:37:04,354,145,156
2011.07.11.,23:21:53:43,310,125,47
2011.06.26.,07:42:10:30,383,180,171
我正在嘗試撰寫一個簡單的 Bash 程式,它告訴“與前面的距離”小于提供的引數($1)的日期和時間到目前為止我寫道:
#!/bin/bash
if [ $# -eq 0 -o $# -gt 1 ]
then
echo "wrong number of parameters"
fi
i=0
fdistance=()
input='auto.txt'
while IFS= read -r line
do
year=${line::4}
month=${line:5:2}
day=${line:8:2}
hour=${line:12:2}
min=${line:15:2}
sec=${line:18:2}
hthsec=${line:21:2}
fdistance=$(cut -d, -f 4)
if [ "$fdistance[$i]" -lt "$1" ]
then
echo "$year[$i]:$month[$i]:$day[$i],$hour[$i]:$min[$i]:$sec[$i]:$hthsec[$i]"
fi
i=`expr $i 1`
done < "$input"
但這給出了“需要整個運算式”的錯誤并且根本不起作用。
uj5u.com熱心網友回復:
如果您可以選擇使用awk,則整個程序可以簡化為:
awk -F, -v dist=150 '$4<dist {split($1,d,"."); print d[1]":"d[2]":"d[3]","$2}' file
在上面的示例中,距離(欄位 4, $4)小于dist變數值的任何記錄將日期欄位(欄位 1, $1)和splits()欄位放入陣列中d,"."其中前 3 個元素將是year, mo,day然后簡單地列印這三個元素的輸出由":"(消除"."了欄位末尾的雜散)分隔。時間(欄位 2, $2)輸出不變。
示例使用/輸出
使用 中的示例資料file,您可以執行以下操作:
$ awk -F, -v dist=150 '$4<dist {split($1,d,"."); print d[1]":"d[2]":"d[3]","$2}' file
2009:03:10,17:46:17:81
2018:01:05,00:30:37:04
2011:07:11,23:21:53:43
它以請求的格式提供距離小于150. 如果您awk從腳本中呼叫,則可以將150第一個引數中的傳入引數傳遞給腳本。
您還可以通過將第一個欄位中的':'每個替換為 a并輸出'.'第一個欄位gsub()的子字串以substr()洗掉最后一個字符來完成此任務,例如
awk -F, -v dist=150 '$4<dist {gsub(/[.]/,":",$1); print substr($1,0,length($1)-1),$2}' file
(相同的輸出)
而分析資料是靠在字串處理的外殼或bash,在實踐中很好的鍛煉awk將是數量級比一個shell腳本更快。處理一百萬行檔案——awk與使用 shell 腳本的幾分鐘(或幾小時)相比,運行時間的差異可能是幾秒鐘。
如果這是一個在 shell 中學習字串處理的練習,只需將它放在你的后口袋里,以便日后了解它awk是真正的文本處理瑞士軍刀。(值得努力學習)
uj5u.com熱心網友回復:
你會嘗試以下方法嗎:
#/bin/bash
if (( $# != 1 )); then
echo "usage: $0 max_distance_from_the_front" >& 2 # output error message to the stderr
exit 1
fi
input="auto.txt"
while IFS=, read -r mydate mytime speed fdist bdist; do # split csv and assign variables
mydate=${mydate%.}; mydate=${mydate//./:} # reformat the date string
if (( fdist < $1 )); then # if the front disatce is less than $1
echo "$mydate,$mytime" # then print the date and time
fi
done < "$input"
與 Keldorn 具有相同引數的示例輸出:
$ ./test.sh 130
2009:03:10,17:46:17:81
2011:07:11,23:21:53:43
uj5u.com熱心網友回復:
你的腳本中有一些奇怪的東西:
- 為什么是
fdistance陣列。這是沒有必要的(這里做錯了),因為檔案是逐行讀取的。 - 什么是
cut該行的fdistance=$(cut -d, -f 4)應該切,有什么輸入? - (注意:當引數無效時,最好立即結束腳本。在下面的示例中添加。)
這是一個作業版本(除了決議日期,但這不是你的問題,所以我跳過了它):
#!/usr/bin/env bash
if [ $# -eq 0 -o $# -gt 1 ]
then
echo "wrong number of parameters"
exit 1
fi
input='auto.txt'
while IFS= read -r line
do
fdistance=$(echo "$line" | awk '{split($0,a,","); print a[4]}')
if [ "$fdistance" -lt "$1" ]
then
echo $line
fi
done < "$input"
示例輸出:
$ ./test.sh 130
2009.03.10.,17:46:17:81,57,102,57
2011.07.11.,23:21:53:43,310,125,47
$
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/359458.html
上一篇:如何使用sed列印網站的標題
