【问题标题】:different shell behaviour: bash omits newline, zsh keeps it不同的 shell 行为:bash 省略换行符,zsh 保留它
【发布时间】:2017-05-08 12:01:48
【问题描述】:

我有一个脚本可以搜索包含“TODO”的源文件 请注意 cmets 内部。此外,我使用grepgit blameuniqsort 的串联来获得 由撰写 TODO 评论的人排序的列表。

以下在 bash 和 zsh 中可以正常工作:

#!/bin/bash

for FILE in $(grep -r -i "todo" apps/business | awk '{print $1}' | sed 's/://' | sed 's/\#//') 
do
git blame $FILE | grep -i "todo"
done | sort -k2 | uniq

现在我想计算所有条目。而不是调用(时间昂贵) grep/git blame 再次,我想将所有内容保存到 $MATCHES 以计算它 无需再次评估。

MATCHES=$(for FILE in $(grep -r -i "todo" apps/business | awk '{print $1}' | sed 's/://' | sed 's/\#//') 
do
    git blame $FILE | grep -i "todo"
done | sort -k2 | uniq)

echo $MATCHES

这就是我在 bash/zsh 中遇到不同行为的地方:

zsh:返回与第一个脚本相同的(如预期的那样)

bash: 忽略 git blame 的换行符,将所有内容放在一行。 wc -l 计为 1 行。

我在这里缺少什么?为什么 bash 在这里表现不同? 以及如何让 bash 不忽略换行符?

【问题讨论】:

  • 试试echo "$MATCHES"。如果没有引号,bash 将根据 IFS 的值将变量解析为单词。

标签: linux bash shell scripting zsh


【解决方案1】:

zsh 默认不对不带引号的参数扩展 $MATCH 执行分词。使用echo "$MATCHES" | wc -lbash 应该也可以。

请注意,这是迭代命令输出的错误方法;请改用while 循环和read 命令。

grep -ri "todo" apps/business | awk '{print $1}' | sed -e 's/://' -e 's/\#//' |
  while IFS= read -r FILE; do
    git blame "$FILE" | grep -i todo
  done | sort -k2 | uniq

【讨论】:

  • 你能简单解释一下为什么for是错误的方式,而whileread更好吗?谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多