如何使用 awk sed 或 cut 命令在匹配模式后打印一行
How to print one line after the matching pattern using awk sed or cut command
我想打印文本文件的内容直到模式匹配的一个字符。我使用了 awk
命令但未能获得所需的输出。
文件:
>cat abc1.txt
2020-05-02 07:48:44+0000
我尝试过的:
>cat abc1.txt | awk '{print }'
2020-05-02
期望的输出:
2020-05-02 07:48
请帮助我。
您可以使用 awk 中的 sub
函数删除最后一次出现 :
后的所有内容:
awk '{sub(/:[^:]*$/, "")} 1' abc1.txt
2020-05-02 07:48
$ echo '2020-05-02 07:48:44+0000' | awk -F: -v OFS=: '{print , }'
2020-05-02 07:48
$ echo '2020-05-02 07:48:44+0000' | cut -d: -f1-2
2020-05-02 07:48
您可以将默认字段分隔符更改为 :
字符并打印前两个字段
第一个解决方案:能否请您尝试以下。
awk 'match([=10=],/^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}/){print substr([=10=],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}).*//' Input_file
第 4 种解决方案: 如果您的 Input_file 始终具有相同的格式输入,并且您无需验证日期的语法,那么试试。
awk 'match([=13=],/^.*:/){print substr([=13=],RSTART,RLENGTH-1)}' Input_file
第5种解决方法:只添加代入运算的awk解决方法
awk '{sub(/:[0-9]{2}\+.*/,"")} 1' Input_file
方案六:设置字段分隔符值,只打印需要的字段。
awk -F' |:' '{print ,":"}' Input_file
使用输入和输出字段分隔符 (:
) 并使用 GNU awk 删除最后一列:
awk 'BEGIN{FS=OFS=":"} {NF--; print}' abc1.txt
或更短:
awk 'BEGIN{FS=OFS=":"} {NF--}1' abc1.txt
输出:
2020-05-02 07:48
参见:8 Powerful Awk Built-in Variables – FS, OFS, RS, ORS, NR, NF, FILENAME, FNR
I want to print the content of text file till one character of pattern matching.
匹配你要保留的正则表达式:
[^:]*:[^:]*
两个等效的 sed 命令只保留与之匹配的内容:
sed 's|\([^:]*:[^:]*\).*||'
sed -E 's|([^:]*:[^:]*).*||'
示例输出:
$ echo '2020 07:48:40:40+0000'|sed 's|\([^:]*:[^:]*\).*||'
2020 07:48
假设您已经对问题的性质进行了公正的表述,则不需要 awk
、sed
或 cut
。以下是仅使用 bash
内置函数处理文本的四种方法:
1。 bash
正则表达式
[[ $(<./abc1.txt) =~ (^.+): ]] && printf %s "${BASH_REMATCH[1]}"
$(<./abc1.txt)
:读入文件内容abc1.txt
,效率比cat
高bash
自己的man
页面
=~
:正则表达式运算符
(^.+):
:捕获从行首到前面字符的每个字符最后的冒号
${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 Programmer's Manual - STRFTIME(3)
),并使用输出字符串 "%F %R"
重新格式化,在本例中表示类似于原始日期字符串,但没有时区且没有 seconds.
4。 printf
printf
用于格式化文本。所以这里它只是格式化文本以显示前 16 个字符(它实际上将第一个字段的列宽限制为 16 个字符的宽度,但那是废话):
printf '%16.16s\n' "$(<./abc1.txt)"
5。子串
类似于 (4),但使用参数替换:
: "$(<./abc1.txt)"
printf "${_:0:16}"
除了 (3)
¹ none 调用外部程序或命令,这提供了更多的可移植性,更好的 reliability/robustness,更有效的执行(一般来说,但这不会除非您正在处理数百个或更多的日期或文件)和更少的系统资源。
awk
和 sed
是强大的大炮,而不是特别轻量级的工具(它们本身都是成熟的、图灵完备的脚本语言)。不要仅仅因为其他人都这样做,或者因为这是你所知道的就去接触他们:学习 bash
作为 shell 可以做什么,你会在未来受益匪浅。
¹ 一些系统包含一个 printf
版本,可以使用 strftime
识别的任何标志来格式化日期,这将是一个很好的选择到 date
(如果可用)。 printf --help
或 man bash
(在有关内置的部分下)将显示此选项是否存在。
我想打印文本文件的内容直到模式匹配的一个字符。我使用了 awk
命令但未能获得所需的输出。
文件:
>cat abc1.txt
2020-05-02 07:48:44+0000
我尝试过的:
>cat abc1.txt | awk '{print }'
2020-05-02
期望的输出:
2020-05-02 07:48
请帮助我。
您可以使用 awk 中的 sub
函数删除最后一次出现 :
后的所有内容:
awk '{sub(/:[^:]*$/, "")} 1' abc1.txt
2020-05-02 07:48
$ echo '2020-05-02 07:48:44+0000' | awk -F: -v OFS=: '{print , }'
2020-05-02 07:48
$ echo '2020-05-02 07:48:44+0000' | cut -d: -f1-2
2020-05-02 07:48
您可以将默认字段分隔符更改为 :
字符并打印前两个字段
第一个解决方案:能否请您尝试以下。
awk 'match([=10=],/^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}/){print substr([=10=],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}).*//' Input_file
第 4 种解决方案: 如果您的 Input_file 始终具有相同的格式输入,并且您无需验证日期的语法,那么试试。
awk 'match([=13=],/^.*:/){print substr([=13=],RSTART,RLENGTH-1)}' Input_file
第5种解决方法:只添加代入运算的awk解决方法
awk '{sub(/:[0-9]{2}\+.*/,"")} 1' Input_file
方案六:设置字段分隔符值,只打印需要的字段。
awk -F' |:' '{print ,":"}' Input_file
使用输入和输出字段分隔符 (:
) 并使用 GNU awk 删除最后一列:
awk 'BEGIN{FS=OFS=":"} {NF--; print}' abc1.txt
或更短:
awk 'BEGIN{FS=OFS=":"} {NF--}1' abc1.txt
输出:
2020-05-02 07:48
参见:8 Powerful Awk Built-in Variables – FS, OFS, RS, ORS, NR, NF, FILENAME, FNR
I want to print the content of text file till one character of pattern matching.
匹配你要保留的正则表达式:
[^:]*:[^:]*
两个等效的 sed 命令只保留与之匹配的内容:
sed 's|\([^:]*:[^:]*\).*||'
sed -E 's|([^:]*:[^:]*).*||'
示例输出:
$ echo '2020 07:48:40:40+0000'|sed 's|\([^:]*:[^:]*\).*||'
2020 07:48
假设您已经对问题的性质进行了公正的表述,则不需要 awk
、sed
或 cut
。以下是仅使用 bash
内置函数处理文本的四种方法:
1。 bash
正则表达式
[[ $(<./abc1.txt) =~ (^.+): ]] && printf %s "${BASH_REMATCH[1]}"
$(<./abc1.txt)
:读入文件内容abc1.txt
,效率比cat
高bash
自己的man
页面=~
:正则表达式运算符(^.+):
:捕获从行首到前面字符的每个字符最后的冒号${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 Programmer's Manual - STRFTIME(3)
),并使用输出字符串 "%F %R"
重新格式化,在本例中表示类似于原始日期字符串,但没有时区且没有 seconds.
4。 printf
printf
用于格式化文本。所以这里它只是格式化文本以显示前 16 个字符(它实际上将第一个字段的列宽限制为 16 个字符的宽度,但那是废话):
printf '%16.16s\n' "$(<./abc1.txt)"
5。子串
类似于 (4),但使用参数替换:
: "$(<./abc1.txt)"
printf "${_:0:16}"
除了 (3)
¹ none 调用外部程序或命令,这提供了更多的可移植性,更好的 reliability/robustness,更有效的执行(一般来说,但这不会除非您正在处理数百个或更多的日期或文件)和更少的系统资源。
awk
和 sed
是强大的大炮,而不是特别轻量级的工具(它们本身都是成熟的、图灵完备的脚本语言)。不要仅仅因为其他人都这样做,或者因为这是你所知道的就去接触他们:学习 bash
作为 shell 可以做什么,你会在未来受益匪浅。
¹ 一些系统包含一个 printf
版本,可以使用 strftime
识别的任何标志来格式化日期,这将是一个很好的选择到 date
(如果可用)。 printf --help
或 man bash
(在有关内置的部分下)将显示此选项是否存在。