使用BASH将CVS diff中的结果排序到一个文件中
我正在尝试更改bash脚本,以便它将所有更改放在每个文件下,而不是重复相同的文件名 因此,我使用以下命令执行一个diff:使用BASH将CVS diff中的结果排序到一个文件中,bash,cvs,Bash,Cvs,我正在尝试更改bash脚本,以便它将所有更改放在每个文件下,而不是重复相同的文件名 因此,我使用以下命令执行一个diff: grep Index ${logs}/${file_diff} | cvs -q diff -r $pTag $pathDir | sed -r 's/^.+\///' > ${logs}/${output_filename} 以上内容将显示输出文件名中上一个标记的更改结果。但问题在于pathDir pathDir在相同的文件中有更改,但每个主题的路径不同: 因此p
grep Index ${logs}/${file_diff} | cvs -q diff -r $pTag $pathDir | sed -r 's/^.+\///' > ${logs}/${output_filename}
以上内容将显示输出文件名中上一个标记的更改结果。但问题在于pathDir
pathDir
在相同的文件中有更改,但每个主题的路径不同:
因此pathDir
包含指向
this/is/the/path/to/the/changes/for/apples
this/is/the/path/to/the/changes/for/bananas
this/is/the/path/to/the/changes/for/grapes
但在这些路径中,文件名change.dat包含所有更改
我是否可以更改grep以显示just change.dat下苹果、香蕉和葡萄的所有更改
目前,它显示的变化如下:
this/is/the/path/to/the/changes/for/apples/change.dat
{Apple changes here}
this/is/the/path/to/the/changes/for/bananas/change.dat
{Banana changes here}
this/is/the/path/to/the/changes/for/grapes/change.dat
{Grape changes here}
由于更改在change.dat中,我想合并它们,以便只显示change.dat
中的更改
谢谢
#!/bin/bash
# the above shebang line MUST be #!/bin/bash, since we use features not in /bin/sh
exec 3>/dev/null # start out with FD 3 writing to /dev/null
while read -r; do # iterate over lines in the cvs diff
if [[ $REPLY = "Index: "* ]]; then # when we see a line starting with "Index: "...
full_filename=${REPLY%"Index: "} # ...extract the filename
base_filename=${full_filename##*/} # ...then extract only the basename
exec 3>>"$base_filename" # ...then open FD 3 to append to the basename
printf '%s\n' "$REPLY" >&3 # ...then write the index line itself
else # for lines that don't start with "Index: "...
printf '%s\n' "$REPLY" >&3 # ...write the line to the existing FD3
fi
done < <(cvs -q diff -r "$pTag" "$pathDir") # do the above for the output from cvs diff
有关逐行读取输入的方法的更多信息,请参阅
有关上面使用的字符串操作技术的更多信息,或者有关bash中字符串操作的更温和的介绍,请参见
有关如何使用exec
的更多信息,请参见此处(页面的其他部分也可能是很好的阅读资料)。有关样式的一些基本说明--${foo}
作为独立参数使用时,不会超过$foo
。对扩展安全性有很大影响的是引用--
“$foo”总是会扩展成一个参数,而$foo
或${foo}
可以是零、一或多个……另外,您最初的grep
实际上做了什么吗?因为它从左边的内容读取输入(管道从左到右),所以它永远看不到右边cvs diff
的输出,也不能以任何方式与之交互(因为cvs diff
据我所知,它不从stdin读取…这是这两个进程之间的唯一连接)谢谢你的帮助,我真的很感激。我使用的grep显示的是diff的结果,而不是管道中使用的diff。它实际上使用的是在这个文件${file_diff}中创建的diff。谢谢你指出这一点。我正在阅读下面的答案,并在我的脚本中进行测试。Thankstorry我在定位生成${logs}/${output_filename}的位置时遇到问题。输出。@Raj,在第一种情况下,您希望将其设置为“$logs/$base\u filename””。在第二个示例中,所有输出都合并到stdout.sorry,但根本没有从中创建文件。我在顶部替换了这个:exec 3>>“$$logs/$base\u filename”。不确定它为什么不生成文件。@Raj,不要更改顶部的文件,更改循环中的文件。在顶部,您还不知道正在处理的文件是什么,因此基本文件名是未设置的。我认为您版本中的$$
是一个打字错误,不是您试图完成的任务的合法表示。除此之外,set-x
是您调试的朋友。我猜您的代码从未看到索引
行(这意味着[[$REPLY=“Index:*]]
测试从未匹配);检查set-x
输出将解释为什么会这样。
#!/bin/bash
# the above shebang line MUST be #!/bin/bash, since we use features not in /bin/sh
while read -r; do # iterate over lines in the cvs diff
if [[ $REPLY = "Index: "* ]]; then # when we see a line starting with "Index: "...
full_filename=${REPLY%"Index: "} # ...extract the filename
base_filename=${full_filename##*/} # ...then extract only the basename
fi
# print to stdout if and only if the current filename is change.dat
[[ $base_filename = change.dat ]] && printf '%s\n' "$REPLY"
done < <(cvs -q diff -r "$pTag" "$pathDir") # do the above for the output from cvs diff