[英]Use Awk to extract substring
Given a hostname in format of aaa0.bbb.ccc
, I want to extract the first substring before .
给定
aaa0.bbb.ccc
格式的主机名,我想提取之前的第一个子字符串.
, that is, aaa0
in this case. ,即本例中的
aaa0
。 I use following awk script to do so,我使用以下 awk 脚本来执行此操作,
echo aaa0.bbb.ccc | awk '{if (match($0, /\./)) {print substr($0, 0, RSTART - 1)}}'
While the script running on one machine A
produces aaa0
, running on machine B
produces only aaa
, without 0
in the end.虽然在一台机器
A
上运行的脚本产生aaa0
,但在机器B
上运行只产生aaa
,最后没有0
。 Both machine runs Ubuntu/Linaro
, but A
runs newer version of awk(gawk with version 3.1.8 while B
with older awk (mawk with version 1.2)两台机器都运行
Ubuntu/Linaro
,但A
运行较新版本的 awk(gawk 使用 3.1.8 版,而B
使用旧版 awk(mawk 使用 1.2 版)
I am asking in general, how to write a compatible awk script that performs the same functionality ...我一般都在问,如何编写一个兼容的 awk 脚本来执行相同的功能......
You just want to set the field separator as .
您只想将字段分隔符设置为
.
using the -F
option and print the first field:使用
-F
选项并打印第一个字段:
$ echo aaa0.bbb.ccc | awk -F'.' '{print $1}'
aaa0
Same thing but using cut:同样的事情,但使用剪切:
$ echo aaa0.bbb.ccc | cut -d'.' -f1
aaa0
Or with sed
:或使用
sed
:
$ echo aaa0.bbb.ccc | sed 's/[.].*//'
aaa0
Even grep
:甚至
grep
:
$ echo aaa0.bbb.ccc | grep -o '^[^.]*'
aaa0
或者只是使用剪切:
echo aaa0.bbb.ccc | cut -d'.' -f1
I am asking in general, how to write a compatible awk script that performs the same functionality ...
我一般都在问,如何编写一个兼容的 awk 脚本来执行相同的功能......
To solve the problem in your quesiton is easy.解决问题中的问题很容易。 (check others' answer).
(检查其他人的答案)。
If you want to write an awk script, which portable to any awk implementations and versions (gawk/nawk/mawk...) it is really hard, even if with --posix (gawk)如果您想编写一个可移植到任何 awk 实现和版本(gawk/nawk/mawk...)的 awk 脚本,即使使用 --posix (gawk) 也非常困难
for example:例如:
\x
escape, some not\x
转义,有些不支持FS
interpreter works differently FS
解释器的工作方式不同 well all the points above are just spoken in general.好吧,以上所有观点都只是笼统地说。 Back to your problem, you problem is only related to fundamental feature of awk.
回到您的问题,您的问题仅与 awk 的基本功能有关。
awk '{print $x}'
the line like that will work all awks. awk '{print $x}'
这样的行适用于所有 awk。
There are two reasons why your awk line behaves differently on gawk and mawk:您的 awk 行在 gawk 和 mawk 上表现不同的原因有两个:
your used substr()
function wrongly.您错误地使用了
substr()
函数。 this is the main cause.这是主要原因。 you have
substr($0, 0, RSTART - 1)
the 0
should be 1
, no matter which awk do you use.你有
substr($0, 0, RSTART - 1)
0
应该是1
,无论你使用哪个 awk 。 awk array, string idx etc are 1-based. awk 数组、字符串 idx 等都是从 1 开始的。
gawk and mawk implemented substr()
differently. gawk 和 mawk 以不同的方式实现
substr()
。
You don't need awk for this...你不需要 awk 这...
echo aaa0.bbb.ccc | cut -d. -f1
cut -d. -f1 <<< aaa0.bbb.ccc
echo aaa0.bbb.ccc | { IFS=. read a _ ; echo $a ; }
{ IFS=. read a _ ; echo $a ; } <<< aaa0.bbb.ccc
x=aaa0.bbb.ccc; echo ${x/.*/}
Heavier options:较重的选项:
sed:
echo aaa0.bbb.ccc | sed 's/\..*//'
sed 's/\..*//' <<< aaa0.bbb.ccc
awk:
echo aaa0.bbb.ccc | awk -F. '{print $1}'
awk -F. '{print $1}' <<< aaa0.bbb.ccc
You do not need any external command at all, just use Parameter Expansion in bash:您根本不需要任何外部命令,只需在 bash 中使用参数扩展:
hostname=aaa0.bbb.ccc
echo ${hostname%%.*}
if you don't want to change the input field separator, then it's possible to use split function:如果您不想更改输入字段分隔符,则可以使用拆分功能:
echo "some aaa0.bbb.ccc text" | awk '{split($2, a, "."); print a[1]}'
documentation : 文档:
split(string, array [, fieldsep [, seps ] ])
Divide string into pieces separated by fieldsep
and store the pieces in array and the separator
strings in the seps array.
awk
is still the cleanest approach : awk
仍然是最干净的方法:
mawk NF=1 FS='[.]' <<< aaa0.bbb.ccc
aaa0
If there's stuff before or after :如果之前或之后有东西:
mawk ++NF FS='[.].+$|^[^ ]* ' OFS= <<< 'some aaa0.bbb.ccc text' mawk '$!NF=$2' FS='[ .]' <<< 'some aaa0.bbb.ccc text'
aaa0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.