例如。
echo "abc-1234a :" | grep <do-something>
只打印出abc-1234a
echo "abc-1234a :" | grep <do-something>
只打印出abc-1234a
echo "abc-1234a :" | egrep -o '^[^:]+'
......虽然这也将匹配没有冒号的行。如果你只想匹配包含冒号的行,并且你必须仅使用grep,那么这可能会起作用:
echo "abc-1234a :" | grep : | egrep -o '^[^:]+'
当然,只有在您的echo "abc-1234a :"
是一个可能被替换为多行输入的示例时,这才有意义。cut
:echo "abc-1234a :" | cut -d: -f1
而且 sed
总是可用的...
echo "abc-1234a :" | sed 's/ *:.*//'
对于最后一个问题,如果你只想打印包含冒号的行,则将其更改为:
echo "abc-1234a :" | sed -ne 's/ *:.*//p'
事实上,你甚至可以纯粹使用bash来做到这一点:
while read line; do
field="${line%%:*}"
# do stuff with $field
done <<<"abc-1234a :"
要获取有关%%
位的信息,可以使用man bash
并搜索"Parameter Expansion"。
更新:
你说:
它是冒号前输入的第一行字符。虽然输入可能有多行。
使用grep
的解决方案可能不是最好的选择,因为它们还将打印可能包括冒号的后续行中的数据。当然,也有许多其他方式来满足这个要求。我们将从示例输入开始:
$ function sample { printf "abc-1234a:foo\nbar baz:\nNarf\n"; }
$ sample
abc-1234a:foo
bar baz:
Narf
你可以使用多个管道符,例如:
$ sample | head -1 | grep -Eo '^[^:]*'
abc-1234a
$ sample | head -1 | cut -d: -f1
abc-1234a
或者你可以使用sed仅处理第一行:
$ sample | sed -ne '1s/:.*//p'
abc-1234a
或者告诉sed在打印第一行后退出(这比读取整个文件要快):
$ sample | sed 's/:.*//;q'
abc-1234a
或者做同样的事情,但只有在找到冒号时才显示输出(出于安全考虑):
$ sample | sed -ne 's/:.*//p;q'
abc-1234a
或者让awk做同样的事情(分别与最后3个示例相同):$ sample | awk '{sub(/:.*/,"")} NR==1'
abc-1234a
$ sample | awk 'NR>1{nextfile} {sub(/:.*/,"")} 1'
abc-1234a
$ sample | awk 'NR>1{nextfile} sub(/:.*/,"")'
abc-1234a
在bash中,甚至不需要使用管道:
$ read line < <(sample)
$ printf '%s\n' "${line%%:*}"
abc-1234a
sed '/:/{ s/:.*//; q;}'
而不是假设只有输入的第一行是有意义的。 - William Pursellegrep -o '^[^:]+'
等同于 grep -o '^[^:]\+'
。 - kenorbsed -e 's/^\([^:]\+\).*/\1/'
进行比较。GNU sed的行为与GNU grep相同,但在FreeBSD、OSX、Solaris等系统中则不同。有趣的是,这种行为甚至在Linux文档中得到了支持——来自regex(7)
手册的倒数第二段描述部分:'|'、'+'和'?'是普通字符,没有它们功能的等价物。
。 - ghoti只用sed就可以实现你想要的功能。
以下是一个例子:
#!/bin/sh
filename=$1
pattern=yourpattern
# flag -n disables print everyline (default behavior)
sed -n "
1,/$pattern/ {
/$pattern/n # skip line containing pattern
p # print lines ranging from line 1 untill pattern
}
" $filename
exit 0
这至少适用于GNU的sed。对于其他sed也应该有效,除了注释(一些sed实现不支持注释)。