簡體   English   中英

如何使用 awk sed 或剪切命令在匹配模式后打印一行

[英]How to print one line after the matching pattern using awk sed or cut command

我想打印文本文件的內容,直到模式匹配一個字符。 我使用awk命令,但未能獲得所需的 output。

文件:

>cat abc1.txt
2020-05-02 07:48:44+0000

我試過的:

>cat abc1.txt | awk '{print $1}'
2020-05-02

所需的 output:

2020-05-02 07:48

請幫我。

$ echo '2020-05-02 07:48:44+0000' | awk -F: -v OFS=: '{print $1, $2}'
2020-05-02 07:48
$ echo '2020-05-02 07:48:44+0000' | cut -d: -f1-2
2020-05-02 07:48

您可以將默認字段分隔符更改為:字符並打印前兩個字段

第一個解決方案:您能否嘗試以下操作。

awk 'match($0,/^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}/){print substr($0,RSTART,RLENGTH)}'  Input_file

第二種解決方案:使用rev + awk使我們的替換更容易。

rev Input_file | awk '{sub(/[^:]*:/,"")} 1' | rev

第三種解決方案:使用sed的臨時緩沖能力。

sed -E 's/([0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}).*/\1/' Input_file

第四種解決方案:如果您的 Input_file 始終具有相同的輸入格式並且您不需要驗證日期的語法,請嘗試。

awk 'match($0,/^.*:/){print substr($0,RSTART,RLENGTH-1)}' Input_file

第 5 種解決方案:僅添加替代操作 awk 解決方案。

awk '{sub(/:[0-9]{2}\+.*/,"")} 1'  Input_file

第 6 種解決方案:設置字段分隔符值並僅打印需要的字段。

awk -F' |:' '{print $1,$2":"$3}' Input_file

使用輸入和 output 字段分隔符 ( : ) 並使用 GNU awk 刪除最后一列:

awk 'BEGIN{FS=OFS=":"} {NF--; print}' abc1.txt

或更短:

awk 'BEGIN{FS=OFS=":"} {NF--}1' abc1.txt

Output:

2020-05-02 07:48

請參閱: 8 個強大的 Awk 內置變量 - FS、OFS、RS、ORS、NR、NF、FILENAME、FNR

假設您已經對問題的性質給出了公平的表示,則不需要awksedcut 以下是僅使用bash內置插件處理文本的四種方法:

1. bash正則表達式

[[ $(<./abc1.txt) =~ (^.+): ]] && printf %s "${BASH_REMATCH[1]}"
  • $(<./abc1.txt) :讀取文件abc1.txt的內容,根據bash自己的man頁比cat更有效

  • =~ : 正則表達式運算符

  • (^.+): : 捕獲從行首到最后一個冒號之前的每個字符

  • ${BASH_REMATCH[1]} :存儲正則表達式匹配的子串列表; 第一個捕獲組(在模式的括號內)存儲在索引 1

2 bash參數代換

: "$(<./abc1.txt)"
printf %s "${_%:*}"
  • ${_%:*}下划線引用上一條命令的參數,即文件內容; 並且替換會刪除從最后一個冒號到字符串末尾的所有內容

3. date

由於很清楚您正在使用日期,並且以明確定義的格式 (ISO-8601) 表示,因此date命令可以執行旨在執行的操作:

# -j flag available on macOS:
date -jf '%F %T%z' "$(<./abc1.txt)" +'%F %R'
# -d option on other systems:
# [credit: @WalterA (see comments below)]
date -d "$(<./abc1.txt)" +"%F %R"

這使用輸入格式字符串"%F %T%z"解析日期,該字符串描述了日期字符串的每個組成部分所代表的內容(參見Linux 程序員手冊 - STRFTIME(3) ),並重新格式化使用 output 字符串"%F %R" ,在這種情況下,它表示與原始日期字符串類似但沒有時區和秒數的日期字符串。

4. printf

printf用於格式化文本。 所以這里它只是格式化文本以顯示前 16 個字符(它實際上將第一個字段的列寬限制為 16 個字符的寬度,但那是廢話):

printf '%16.16s\n' "$(<./abc1.txt)"

5. Substring

與 (4) 類似,但使用參數替換:

: "$(<./abc1.txt)"
printf "${_:0:16}"

除了(3) ¹ 沒有調用外部程序或命令,這提供了更多的可移植性、更高的可靠性/健壯性、更有效的執行(一般來說,除非您正在處理數百或更多的日期或文件,否則這將無法衡量),以及更少的系統資源。

awksed是強大的大炮,而不是特別輕量級的工具(它們都是成熟的、圖靈完備的腳本語言)。 不要僅僅因為其他人都這樣做,或者因為它是你所知道的:了解 bash 作為bash可以做什么,你會從中受益匪淺。

¹

Yon 可以在 awk 中使用sub function 刪除最后一次出現后的所有內容:

awk '{sub(/:[^:]*$/, "")} 1' abc1.txt

2020-05-02 07:48

我想打印文本文件的內容,直到模式匹配一個字符。

與您要保留的內容匹配的正則表達式:

[^:]*:[^:]*

兩個等效的 sed 命令僅保留與之匹配的內容:

sed 's|\([^:]*:[^:]*\).*|\1|'
sed -E 's|([^:]*:[^:]*).*|\1|'

樣品 output:

$ echo '2020 07:48:40:40+0000'|sed 's|\([^:]*:[^:]*\).*|\1|'
2020 07:48

暫無
暫無

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

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