37

给定格式为 的主机名aaa0.bbb.ccc,我想提取 之前的第一个子字符串.,即aaa0在本例中。我使用以下 awk 脚本来执行此操作,

echo aaa0.bbb.ccc | awk '{if (match($0, /\./)) {print substr($0, 0, RSTART - 1)}}'

在一台机器上运行的脚本A产生aaa0,在机器上运行B只产生aaa,最终没有0。两台机器都运行Ubuntu/Linaro,但A运行较新版本的 awk(gawk 使用 3.1.8 版,而B使用旧版 awk(mawk 使用 1.2 版)

我一般都在问,如何编写一个兼容的 awk 脚本来执行相同的功能......

4

5 回答 5

72

您只想将字段分隔符设置为.使用该-F选项并打印第一个字段:

$ echo aaa0.bbb.ccc | awk -F'.' '{print $1}'
aaa0

同样的事情,但使用剪切:

$ echo aaa0.bbb.ccc | cut -d'.' -f1
aaa0

或与sed

$ echo aaa0.bbb.ccc | sed 's/[.].*//'
aaa0

甚至grep

$ echo aaa0.bbb.ccc | grep -o '^[^.]*'
aaa0
于 2013-04-16T15:09:19.597 回答
6

我一般都在问,如何编写一个兼容的 awk 脚本来执行相同的功能......

解决问题中的问题很容易。(检查其他人的答案)。

如果您想编写一个可移植到任何 awk 实现和版本(gawk/nawk/mawk...)的 awk 脚本,即使使用 --posix (gawk) 也非常困难

例如:

  • 一些 awk 以字符的形式处理字符串,一些以字节为单位
  • 有些支持\x逃生,有些不支持
  • FS口译员的工作方式不同
  • 关键字/保留词缩写限制
  • 一些运营商限制,例如**
  • 甚至相同的 awk impl。(例如 gawk),4.0 和 3.x 版本也有区别。
  • 某些功能的实现也不同。(你的问题是一个例子,见下文)

好吧,以上所有观点都只是笼统地说。回到您的问题,您的问题仅与 awk 的基本功能有关。awk '{print $x}'这样的行将适用于所有 awks。

您的 awk 行在 gawk 和 mawk 上表现不同的原因有两个:

  • substr()错误地使用了功能。这是主要原因。无论您使用哪个 awk,您都拥有substr($0, 0, RSTART - 1)should 0be 。1awk 数组、字符串 idx 等都是从 1 开始的。

  • gawk 和 mawk 的实现substr()方式不同。

于 2013-04-16T15:35:19.033 回答
6

或者只是使用剪切:

echo aaa0.bbb.ccc | cut -d'.' -f1
于 2013-04-16T15:11:04.507 回答
3

你不需要 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/.*/}

较重的选项:

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 
于 2013-04-16T15:12:20.560 回答
2

您根本不需要任何外部命令,只需在 bash 中使用参数扩展:

hostname=aaa0.bbb.ccc
echo ${hostname%%.*}
于 2013-04-16T15:21:02.950 回答