12

例如

echo "abc-1234a :" | grep <do-something>

只打印abc-1234a

4

2 回答 2

26

我认为这些更接近您的目标,但是在不知道您真正想要实现的目标的情况下,很难说。

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搜索“参数扩展”。

更新

你说:

它是冒号之前输入的第一行中的字符。输入可以有多行。

那么,解决方案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
于 2012-09-11T00:16:18.540 回答
0

只用 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 的一些实现不支持评论)。

来源:https ://www.grymoire.com/Unix/Sed.html

于 2021-08-13T02:44:44.903 回答