bash 始终在 grep 中包含第一行
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9969414/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Always include first line in grep
提问by jhourback
I often grep CSV files with column names on the first line. Therefore, I want the output of grep to always include the first line (to get the column names) as well as any lines matching the grep pattern. What is the best way to do this?
我经常在第一行使用列名 grep CSV 文件。因此,我希望 grep 的输出始终包括第一行(以获取列名)以及与 grep 模式匹配的任何行。做这个的最好方式是什么?
采纳答案by DigitalRoss
You could include an alternate pattern match for the one of the column names. If a column was called COLthen this would work:
您可以为列名之一包含备用模式匹配。如果列被称为COL,那么这将起作用:
$ grep -E 'COL|pattern' file.csv
回答by kev
sed:
sed:
sed '1p;/pattern/!d' input.txt
awk:
awk:
awk 'NR==1 || /pattern/' input.txt
grep1:
格雷普1:
grep1() { awk -v pattern="${1:?pattern is empty}" 'NR==1 || awk 'NR == 1 || /Incoming/' foo.csv
~pattern' "${2:?filename is empty}"; }
回答by Alex North-Keys
grep doesn't really have a concept of line number, but awk does, so here's an example to output lines contain "Incoming" - and the first line, whatever it is:
grep 并没有真正的行号概念,但 awk 有,所以这里有一个输出行包含“传入”的示例 - 以及第一行,无论它是什么:
#!/bin/sh
pattern="" ; shift
exec awk 'NR == 1 || /'"$pattern"'/' "$@"
You could make a script (a bit excessive, but). I made a file, grep+1, and put this in it:
你可以制作一个脚本(有点过分,但是)。我做了一个文件,grep+1,然后把它放进去:
./grep+1 Incoming
Now one can:
现在可以:
sed -n -e '1p' -e '/pattern/p' < $FILE
edit: removed the "{print;}", which is awk's default action.
编辑:删除了“{print;}”,这是 awk 的默认操作。
回答by Adam Liss
You can use sedinstead of grepto do this:
您可以使用sed代替grep来执行此操作:
#!/bin/bash
IFS='' read -r JUST1LIINE
printf "%s\n" "$JUST1LIINE"
exec "$@"
This will print the first line twice, however, if it happens to contain the pattern.
这将打印第一行两次,但是,如果它碰巧包含该模式。
-ntells sednot to print each line by default.-e '1p'prints the first line.-e '/pattern/p'prints each line that matches the pattern.
-n告诉sed默认情况下不打印每一行。-e '1p'打印第一行。-e '/pattern/p'打印与模式匹配的每一行。
回答by Aaron McDaid
This is a very general solution, for example if you want to sort a file while keeping the first line in place. Basically, "pass the first line through as-is, then do whatever I want (awk/grep/sort/whatever) on the rest of the data."
这是一个非常通用的解决方案,例如,如果您想在保留第一行的同时对文件进行排序。基本上,“通过第一线通过按原样,然后做任何我想(awk/ grep/ sort/无论)上的数据的剩余部分”。
Try this in a script, perhaps calling it keepfirstline(don't forget chmod +x keepfirstlineand to put it in your PATH):
在脚本中试试这个,也许调用它keepfirstline(不要忘记chmod +x keepfirstline并将它放在你的PATH)中:
cat your.data.csv | keepfirstline grep SearchTerm > results.with.header.csv
It can be used as follows:
它可以按如下方式使用:
cat your.data.csv | keepfirstline awk ' < 3' > results.with.header.csv
or perhaps, if you want to filter with awk
或者,如果你想过滤 awk
cat your.data.csv | keepfirstline sort
I often like to sort a file, but keeping the header in the first line
我经常喜欢对文件进行排序,但将标题保留在第一行
$ cat data.csv | (read line; echo "$line"; grep SEARCH_TERM)
keepfirstlineexecutes the command it's given (grep SearchTerm), but only after reading and printing the first line.
keepfirstline执行给定的命令 ( grep SearchTerm),但仅在读取和打印第一行之后执行。
回答by Eyal Levin
Another option:
另外一个选项:
$ echo "title\nvalue1\nvalue2\nvalue3" | (read line; echo "$line"; grep value2)
Example:
例子:
title
value2
Output:
输出:
#!/bin/bash
# grep+1 [<option>...] [<regex>] [<file>...]
# Emits the first line of each input and ignores it otherwise.
# For grep options that have optargs, only the --forms will work here.
declare -a files options
regex_seen=false
regex=
double_dash_seen=false
for arg in "$@" ; do
is_file_or_rx=true
case "$arg" in
-*) is_file_or_rx=$double_dash_seen ;;
esac
if $is_file_or_rx ; then
if ! $regex_seen ; then
regex="$arg"
regex_seen=true
else
files[${#files[*]}]="$arg" # append the value
fi
else
options[${#options[*]}]="$arg" # append the value
fi
done
# We could either open files all at once in the shell and pass the handles into
# one grep call, but that would limit how many we can process to the fd limit.
# So instead, here's the simpler approach with a series of grep calls
if $regex_seen ; then
if [ ${#files[@]} -gt 0 ] ; then
for file in "${files[@]}" ; do
head -n 1 "$file"
tail -n +2 "$file" | grep --label="$file" "${options[@]}" "$regex"
done
else
grep "${options[@]}" # stdin
fi
else
grep "${options[@]}" # probably --help
fi
#--eof
回答by Alex North-Keys
So, I posted a completely different short answer above a while back.
所以,我不久前在上面发布了一个完全不同的简短回答。
However, for those pining for a command that looks like grep in terms of taking all the same options (although this script requires you to use the long options if an optarg is involved), and can cope with weird characters in filenames, etc, etc.. have fun pulling this apart.
但是,对于那些在采用所有相同选项方面看起来像 grep 的命令的人(尽管如果涉及 optarg,此脚本要求您使用长选项),并且可以处理文件名等中的奇怪字符等.. 把它拆开玩得开心。
Essentially it's a grep that always emits the first line. If you think a file with no matching lines should skip emitting that first (header) line, well, that's left as an exercise for the reader. I saved is as grep+1.
本质上,它是一个始终发出第一行的 grep。如果您认为没有匹配行的文件应该跳过发出第一行(标题),那么,这留给读者作为练习。我保存为grep+1.
df -h | grep -E '(^Filesystem|/mnt)' # <<< returns usage of devices, with mountpoint '/mnt/...'
ps aux | grep -E '(^USER|grep)' # <<< returns all grep-process
回答by Sven
All answer were correct. Just another idea for situations to grep the output of a command (and not a file) including the first line could be done like this ;-)
所有的答案都是正确的。对于 grep 命令(而不是文件)的输出(包括第一行)的情况的另一个想法可以这样完成;-)
head -1 <file> && grep ff <file>
The -Eoption of grep enables its regex-mode. The string we grep uses |and can be interpretated as an "or", so we look in the df-exmaple for lines:
在-Egrep的的选项允许它的正则表达式模式。我们 grep 使用的字符串|可以解释为“或”,因此我们在df-exmaple 中查找行:
- starting with
Filesystem(leading '^' in the first sub expression means "line starts with") - and lines, that contains
/mnt
- 开头
Filesystem(第一个子表达式中的前导'^'表示“行开头”) - 和行,其中包含
/mnt
Another, way could be to pipe the output into a tempfileand to grep the content like shown in other posts. This can be helpful, if you don't know the content of the first line.
另一种方法可能是将输出通过管道传输到 atempfile并像其他帖子中显示的那样 grep 内容。如果您不知道第一行的内容,这会很有帮助。
head -1 <filename>
回答by scibuff
Just do
做就是了
##代码##and then execute grep
然后执行 grep

