首页 > 解决方案 > 与本地相比,Grep 在 Travis 上的行为不同

问题描述

我继承了一个构建脚本,该脚本通过获取已更改文件的列表并确保它们具有包含当前年份的版权声明来检查我们的 Travis 构建中的版权声明。获取年份的脚本部分是使用 grep 来提取年份,如下所示:

GOSRCFILES=($(git diff --name-only origin/master | grep -v vendor | grep '\.go$'))
for GOFILE in "${GOSRCFILES[@]}"; do
  if grep -q "(C) Copyright" $GOFILE; then
      YEAR_LINE=$(grep -m 1 "(C) Copyright" $GOFILE)
      echo "Year line in ${GOFILE} is '${YEAR_LINE}'"
      YEARS=($(echo $YEAR_LINE | grep -oE '\d{4}'))
      echo "Years is ${YEARS[@]}"
  fi
done

这在本地(在 Mac 上)运行良好,但在 Travis 上运行时失败。本地输出为:

Year line in main.go is ' * (C) Copyright IBM Corp. 2017, 2018 All Rights Reserved.'
Years is 2017 2018

而在特拉维斯它打印:

Year line in main.go is ' * (C) Copyright IBM Corp. 2017, 2018 All Rights Reserved.'
Years is 

如您所见,它找到了版权行,但从中提取YEARS( YEARS=($(echo $YEAR_LINE | grep -oE '\d{4}'))) 的命令失败。我已经阅读了 grep 的手册页,但不明白为什么这个命令的行为会有所不同。

标签: bashgreptravis-ci

解决方案


转义是一个 Perl 扩展,如果没有其他选项\d,通常不支持它。grep请改用[0-9]或 POSIX 类[[:digit:]]。(了解细微的差异;POSIX 依赖于语言环境,但在 Travis 上,语言环境可能并不引人注目。)

切线,如果你只使用一次数组,不要使用数组;你可以避免前grep两次;并且不要对私有变量使用大写;并引用你的变量;并将您的诊断打印到标准错误。

for gofile in $(git diff --name-only origin/master | grep -v vendor | grep '\.go$'); do
  if year_line=$(grep -m 1 "(C) Copyright" "$gofile"); then
    echo "Year line in $gofile is '$year_line'" >&2
    years=($(echo "$year_line" | grep -oE '[[:digit:]]{4}'))
    echo "Years is ${years[@]}" >&2
  fi
done

推荐阅读