从以下命令中我如何消除
之前出现的所有行 Owner RepoName CreatedDate
EDIT命令:
find /opt/site/ -name '.log.txt' | xargs cat | awk '{$NF=""; print $0}' | sed '1i Owner RepoName CreatedDate' | column -t
输出
find: Filesystem loop detected; `/nfs/.snapshot/nightly.4' has the same device number and inode as a directory which is 2 levels higher in the filesystem hierarchy.
find: Filesystem loop detected; `/nfs/.snapshot/nightly.5' has the same device number and inode as a directory which is 2 levels higher in the filesystem hierarchy.
find: Filesystem loop detected; `/nfs/.snapshot/nightly.6' has the same device number and inode as a directory which is 2 levels higher in the filesystem hierarchy.
Owner RepoName CreatedDate
val abc Fri Mar 16 17:01:07 PDT
p1 repo_pc Wed Mar 21 11:34:42 PDT
New fm Mon Mar 19 00:15:51 PD
所需的输出仅为:
Owner RepoName CreatedDate
val abc Fri Mar 16 17:01:07 PDT
p1 repo_pc Wed Mar 21 11:34:42 PDT
New fm Mon Mar 19 00:15:51 PD
答案 0 :(得分:3)
那些发现错误将在stderr上,因此完全绕过你的链,你会想要用2>/dev/null
重定向错误,尽管这会阻止你在find命令中看到任何其他错误。
find /opt/site/ -name '.log.txt' 2>/dev/null | xargs cat | awk '{$NF=""; print $0}' | xargs sed "/Filesystem/d" | sed '1i Owner RepoName CreatedDate' | column -t
一般情况下,如果遇到这样复杂的命令,你应该在遇到错误时将其分解,以便找出问题所在的位置。
让我们拆分这个命令,看看它在做什么:
find /opt/site/ -name '.log.txt' 2>/dev/null
- 找到/ opt / site / named .log.txt
xargs cat
- 一个接一个地获取所有内容
awk '{$NF=""; print $0}'
- 删除最后一栏
xargs sed "/Filesystem/d"
- 将每个条目视为文件,并从这些文件的内容中删除包含Filesystem的所有行。
sed '1i Owner RepoName CreatedDate'
- 在第一行插入所有者RepoName CreatedDate
column -t
- 将给定数据转换为表格
我建议建立命令,并在每个阶段检查输出是否正确。
你的命令有几件令人惊讶的事情:
答案 1 :(得分:0)
您可以通过在第一个管道之前将2> / dev / null附加到you命令的find部分来消除find的错误输出。 [编辑:这是最好的方式,我已经投票道格拉斯了,因为他先在这里;)
但是如果你真的想用sed或awk(想不出为什么?),你可以修改你的awk脚本以跳过以'find:'开头的行:
awk '/^find:/ {next;} {$NF=""; print $0}'
答案 2 :(得分:0)
可悲的是,您似乎正在使用csh或tcsh,其中将标准错误与标准输出重定向很困难。否则道格拉斯的答案就会奏效。但试试这个:
(find /opt/site/ -name '.log.txt' | xargs cat | awk '{$NF=""; print $0}' | sed '1i Owner RepoName CreatedDate' | column -t > output) >&/dev/null
注意围绕命令的大部分的parens。在那些parens中是一个重定向,将标准输出发送到一个名为“output”的文件,而不是发送到您的终端(根据您的意愿命名它 - 或者如果您真的想看到它,请用output
替换/dev/tty
在你的终端)。在这些parens之外是一个重定向,将剩余的错误消息发送到/dev/null
。
对于可怕贝壳的长寿,整件事情是一篇悲惨的评论。
答案 3 :(得分:0)
下一个sed
命令应该完成这项工作(将它与输入文件或管道一起使用):
sed -n '/^Owner/,$ p'
说明:
-n # Disable auto-print.
/^Owner/ # From a line beginning with 'Owner'...
$ # ...until end of input...
p # print
答案 4 :(得分:0)
这完全可以通过Awk脚本实现...
#!/usr/bin/awk -f
BEGIN {
for (i = 1; i < ARGC; i++) {
if (ARGV[i] ~ "^--from=") {
_from = substr(ARGV[i], 8)
delete ARGV[i]
}
}
if (!_from) {
print "No '--from' argument provided!" > "/dev/stderr"
}
}
{
if (_flag) {
print $0
} else if ($0 ~ _from) {
_flag = 1
print $0
}
}
注意;上面的脚本是根据
from-till.awk
(从--from
和--till
搜索表达式中打印出来)改编而成的,因此可能需要针对此特定用例调整添加的命令行选项和变量名
...允许将文件用作输入...
head-trimmer.awk --from="^Owner" file-path.txt
...或重定向,例如EOF
或管道...
head-trimmer.awk --from="^Owner" <<'EOF'
find: Filesystem loop detected; `/nfs/.snapshot/nightly.4' has the same device number and inode as a directory which is 2 levels higher in the filesystem hierarchy.
find: Filesystem loop detected; `/nfs/.snapshot/nightly.5' has the same device number and inode as a directory which is 2 levels higher in the filesystem hierarchy.
find: Filesystem loop detected; `/nfs/.snapshot/nightly.6' has the same device number and inode as a directory which is 2 levels higher in the filesystem hierarchy.
Owner RepoName CreatedDate
val abc Fri Mar 16 17:01:07 PDT
p1 repo_pc Wed Mar 21 11:34:42 PDT
New fm Mon Mar 19 00:15:51 PD
EOF
...和应该将其解析为类似...
Owner RepoName CreatedDate
val abc Fri Mar 16 17:01:07 PDT
p1 repo_pc Wed Mar 21 11:34:42 PDT
New fm Mon Mar 19 00:15:51 PD
... Awk脚本可以更轻松地扩展和/或适应其他用例,正确使用它意味着可以消除对其他程序的不必要调用。
应该可以从管道中消除sed
和column
,并提供一些提示
在{strong>所有输入的开头和结尾处运行的带有Awk的BEGIN
和END
块,例如文件列表,因此对于构建标题和列映射非常有用
在Awk中使用while
和getline
可以解析命令的输出...
#!/usr/bin/awk -f
BEGIN {
for (i = 1; i < ARGC; i++) {
if (ARGV[i] ~ "^--directory=") {
_directory = substr(ARGV[i], 13)
delete ARGV[i]
}
if (ARGV[i] ~ "^--name=") {
_name = substr(ARGV[i], 8)
delete ARGV[i]
}
# ... perhaps add other args to parse
}
# ... build/print header maybe
}
{
cmd = "find " _directory " -name " _name " 2>/dev/null"
while (( cmd | getline _line ) > 0) {
print "_line ->", _line
# ... do some fancy formatting, use a built-in, or another command
# to build desired column output from find results
}
close(cmd)
# ...
}
当试图编写一个Bash脚本,它只是一个带有一些自定义解析的命令的包装程序时,这可能非常方便。
有很多方便的内置Awk函数(GAwk则更多),例如。 split
,length
,并且可以通过Awk脚本中的function
关键字添加更多内容。
数组 / 字典变量也可以在Awk中使用,例如...
BEGIN {
for (i = 1; i < ARGC; i++) {
if (ARGV[i] ~ "^--from=") {
_custom_args["from"] = substr(ARGV[i], 8)
delete ARGV[i]
} else if (ARGV[i] ~ "^--till=") {
_custom_args["till"] = substr(ARGV[i], 8)
delete ARGV[i]
}
}
}
{
# ...
}
但是(如果我没记错的话)应该避免使用诸如
_something[0,1]
之类的多维数组,因为在Awk中,这种情况实际上是_something["0,1"]
使用Awk将列打印为格式良好的表有些棘手,但也可以通过printf
格式设置选项来实现...
#!/usr/bin/awk -f
BEGIN {
printf("%-8s %-13s %s\n", "Owner", "RepoName", "CreatedDate")
}
基本上,
%-8s
告诉Awk至少保留8
个字符,而不管字符串"Owner"
,%-13s
保留13
和{ {1}}告诉Awk在字符串的右/末端用分隔符填充较长的字符串。
将-
与printf
结合使用以防止更长的刺痛可能是有用的...
%.<n>
如果您被卡住,请随时发表评论,我将尝试使用更多技巧再次进行介绍。