2013-04-16 53 views
22

给定一个格式为aaa0.bbb.ccc的主机名,我想提取.之前的第一个子串,即aaa0。我用下面的awk脚本这样做,使用Awk提取子串

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

虽然一体机A产生aaa0上运行脚本,机器B上运行只生产aaa,没有最终0。这两种机器运行Ubuntu/Linaro,但A运行AWK的新版本(呆子与3.1.8版本,而B与旧的awk(mawk 1.2版)

我问在一般情况下,如何编写执行兼容的awk脚本相同的功能...

回答

47

你只想使用-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 
4

或者只是使用切:

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

你并不需要为这个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 
+0

Downvoter,请让我知道这个错误。谢谢 :) – anishsane

1

你不需要任何外部命令不惜一切,只需使用参数扩展在bash:

hostname=aaa0.bbb.ccc 
echo ${hostname%%.*} 
4

我问在一般情况下,如何写兼容的awk脚本, 执行相同的功能...

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

如果你想写一个awk脚本,它可移植到任何awk实现和版本(gawk/nawk/mawk ...)真的很难,即使有--posix(GAWK)

例如:

  • 一些awk的工作在字符串中的字符而言,有的用字节
  • 一些支持\x逃生,一些不
  • FS解释的工作方式不同
  • 关键字/保留字缩写限制
  • 一些运营商的限制如**
  • 甚至相同的awk impl。 (例如gawk),版本4.0和3.x也有区别。
  • 某些功能的实现也不同。 (你的问题是一个例子,见下面)

以上所有的点都只是一般的说法。回到你的问题,你的问题只涉及到awk的基本功能。 awk '{print $x}'这样的线会工作所有的awks。

有两个原因,为什么你的awk线表现不同上观看或mawk:

  • 您使用substr()功能错误。这是主要原因。你有substr($0, 0, RSTART - 1)0应该是1,不管你使用哪个awk。 awk数组,字符串idx等是基于1的。

  • gawk和mawk以不同方式实施substr()