簡體   English   中英

將日期時間格式與 Bash REGEX 匹配

[英]Match datetime format with Bash REGEX

我在 bash 中有這種日期時間格式的數據:

28/11/13 06:20:05 (dd/mm/yy hh:mm:ss)

我需要像這樣重新格式化它:

2013-11-28 06:20:05 (MySQL 日期時間格式)

我正在使用以下正則表達式:

regex='([0-9][0-9])/([0-9][0-9])/([0-9][0-9])\s([0-9][0-9]/:[0-9][0-9]:[0-9][0-9])'

if [[$line=~$regex]]
then
   $line='20$3-$2-$1 $4';
fi

這會產生一個錯誤:

./filename: line 10: [[09:34:38=~([0-9][0-9])/([0-9][0-9])/([0-9][0-9])\s([0-9][0-9]/:[0-9][0-9]:[0-9][0-9])]]: No such file or directory

更新:

我想“逐行”讀取這個文件,解析它並在mysql數據庫中插入數據:

'文件名X':

27/11/13 12:20:05 9984 2885 260 54 288 94 696 1852 32 88 27 7 154
27/11/13 13:20:05 9978 2886 262 54 287 93 696 1854 32 88 27 7 154
27/11/13 14:20:05 9955 2875 262 54 287 93 696 1860 32 88 27 7 154
27/11/13 15:20:04 9921 2874 261 54 284 93 692 1868 32 88 27 7 154
27/11/13 16:20:09 9896 2864 260 54 283 92 689 1880 32 88 27 7 154
27/11/13 17:20:05 9858 2858 258 54 279 92 683 1888 32 88 27 7 154
27/11/13 18:20:04 9849 2853 258 54 279 92 683 1891 32 88 27 7 154
27/11/13 19:20:04 9836 2850 257 54 279 93 683 1891 32 88 27 7 154
27/11/13 20:20:05 9826 2845 257 54 279 93 683 1892 32 88 27 7 154
27/11/13 21:20:05 9820 2847 257 54 278 93 682 1892 32 88 27 7 154
27/11/13 22:20:04 9810 2844 257 54 277 93 681 1892 32 88 27 7 154
27/11/13 23:20:04 9807 2843 257 54 276 93 680 1892 32 88 27 7 154
28/11/13 00:20:05 9809 2843 257 54 276 93 680 1747 29 87 17 6 139
28/11/13 01:20:04 9809 2842 257 54 276 93 680 1747 29 87 17 6 139
28/11/13 02:20:05 9809 2843 256 54 276 93 679 1747 29 87 17 6 139
28/11/13 03:20:04 9808 2842 256 54 276 93 679 1747 29 87 17 6 139
28/11/13 04:20:05 9808 2842 256 54 276 93 679 1747 29 87 17 6 139
28/11/13 05:20:39 9807 2842 256 54 276 93 679 1747 29 87 17 6 139
28/11/13 06:20:05 9804 2840 256 54 276 93 679 1747 29 87 17 6 139

腳本:

#!/bin/bash

echo "Start!"

while IFS='     ' read -ra ADDR;
do
   for line in $(cat results)
   do
      regex='([0-9][0-9])/([0-9][0-9])/([0-9][0-9]) ([0-9][0-9]:[0-9][0-9]:[0-9]$
      if [[ $line =~ $regex ]]; then
         $line="20${BASH_REMATCH[3]}-${BASH_REMATCH[2]}-${BASH_REMATCH[1]} ${BASH_REMATCH[4]}"
      fi
      echo "insert into table(time, total, caracas, anzoategui) values('$line', '$line', '$line', '$line', '$line');"
   done | mysql -user -password database;
done < filenameX

結果:

時間 | 總計 | 加拉加斯| 安佐特吉| 0000-00-00 00:00:00 | 9 | 9 | 9 |
2027-11-13 00:00:00 | 15 | 15 | 15 |

注意:此答案是基於修復 OP 中以 bash 為重點的方法而被接受的。 有關更簡單的基於awk的解決方案,請參閱此答案的最后一部分。

請嘗試以下操作:

line='28/11/13 06:20:05' # sample input

regex='([0-9][0-9])/([0-9][0-9])/([0-9][0-9]) ([0-9][0-9]:[0-9][0-9]:[0-9][0-9])'

if [[ $line =~ $regex ]]; then
  line="20${BASH_REMATCH[3]}-${BASH_REMATCH[2]}-${BASH_REMATCH[1]} ${BASH_REMATCH[4]}"
fi

echo "$line"  # -> '2013-11-28 06:20:05'

至於為什么你的代碼不起作用:

  • 正如@anubhava 所指出的,在[[的右側和]]的左側至少需要 1 個空格。
  • \\s是否在 bash 正則表達式中工作是平台相關的(Linux:是;OSX:否),因此單個文字空間在這里是更安全的選擇。
  • 您的變量分配不正確( $line = ... ) -分配給變量時,切勿在變量名前加上$
  • 您的反向引用不正確( $1 ,...):要在 bash 正則表達式中引用捕獲組(子表達式),您必須使用特殊的${BASH_REMATCH[@]}數組變量; ${BASH_REMATCH[0]}包含匹配的整個字符串, ${BASH_REMATCH[1]}包含第一個捕獲組匹配的內容,依此類推; 相比之下, $1 , $2 , ... 指的是傳遞給 shell 腳本或函數的第 1, 2, ... 參數。

Update ,以解決 OP 的更新問題:

認為以下做你想要的:

# Read input file and store each col. value in separate variables.
while read -r f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15; do

    # Concatenate the first 2 cols. to form a date + time string.
    dt="$f1 $f2"

    # Parse and reformat the date + time string.
    regex='([0-9][0-9])/([0-9][0-9])/([0-9][0-9]) ([0-9][0-9]:[0-9][0-9]:[0-9][0-9])'
    if [[ "$dt" =~ $regex ]]; then
      dt="20${BASH_REMATCH[3]}-${BASH_REMATCH[2]}-${BASH_REMATCH[1]} ${BASH_REMATCH[4]}"
    fi

    # Echo the SQL command; all of them are piped into a `mysql` command
    # at the end of the loop.
    # !! Fill the $f<n> variables in as needed - I don't know which ones you need.
    # !! Make sure the number column name matches the number of values.
    # !! Your original code had 4 column names, but 5 values, causing an error.
    echo "insert into table(time, total, caracas, anzoategui) values('$dt', '$f3', '$f4', '$f5');"

done < filenameX | mysql -user -password database

事后思考:上述解決方案基於對 OP 代碼的改進; 下面是一個簡化的解決方案,它是基於awk的單行解決方案(為了可讀性而分布在多行中 - 對基於 awk 的日期重新格式化的@twalberg 的提示):

awk -v sq=\' '{
 split($1, tkns, "/");
 dt=sprintf("20%s-%s-%s", tkns[3], tkns[2], tkns[1]); 
 printf "insert into table(time,total,caracas,anzoategui) values(%s,%s,%s,%s);", 
   sq dt " " $2 sq, sq $3 sq, sq $4 sq, sq $5 sq
}' filenameX | mysql -user -password database

注意:為了使awk程序中的引用更簡單,通過變量sq ( -v sq=\\' ) 傳入單引號。

Perl 在這里很方便。

dt="28/11/13 06:20:05"
perl -MTime::Piece -E "say Time::Piece->strptime('$dt', '%d/%m/%y %T')->strftime('%Y-%m-%d %T')"
2013-11-28 06:20:05

這可以在沒有任何過於復雜的正則表達式調用的情況下實現:

echo "28/11/13 06:20:05" | awk -F'[/ ]' \
    '{printf "20%s-%s-%s %s\n", $3, $2, $1, $4}'

或者,正如@fedorqui 在評論中所建議的那樣,如果時間戳的來源是date ,則可以為其提供所需的格式選項...

BASH 中的空格是強制性的,因此請使用:

[[ "$line" =~ $regex ]] && echo "${line//\//-}"

你也不能在 BASH 中使用\\s所以使用這個正則表達式:

regex='([0-9][0-9])/([0-9][0-9])/([0-9][0-9]) ([0-9][0-9]:[0-9][0-9]:[0-9][0-9])'

感謝大家提供上面的示例。

未附加“T”

$line='"2020-11-26 10:20:01.000000","the size of the table is 3.5" (inches)","2020-12-11 10:20:02"'
$echo "$line" | sed -r 's#(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2})#\2T\1#g'
"2020-11-26 10:20:01.000000","the size of the table is 3.5" (inches)","2020-12-11 10:20:02"

“T”僅附加到第一列的中間,而不附加到行中具有日期格式的任何其他列

$awk '/[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) (2[0-3]|[01][0-9]):[0-5][0-9]*/{print}' test_file |sed -e 's/\s/\T/'
"2020-11-26T10:20:01.000000","the size of the table is 3.5" (inches)","2020-12-11 10:20:02"

上面帶有分組的示例

$ line='"2020-11-26 10:20:01.000000","the size of the table is 3.5" (inches)","2020-12-11 10:20:02"'
$ regex='([0-9][0-9])-([0-9][0-9])-([0-9][0-9]) ([0-9][0-9]:[0-9][0-9]:[0-9][0-9])'
$ if [[ $line =~ $regex ]]; then line="20${BASH_REMATCH[3]}-${BASH_REMATCH[2]}-${BASH_REMATCH[1]}T${BASH_REMATCH[4]}"; fi
$ echo "$line" 
2026-11-20T10:20:01

#...目的是在具有數百萬條記錄的巨大 csv 文件中的所有字段的日期和時間(相同字段)之間附加“T”,而不僅僅是第一列,所有字段都具有相同的日期格式 YYYY-MM-DD HH24:MI :SS

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM