繁体   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