简体   繁体   中英

Replace the first occurrence with sed

As the example below, I want to keep only the word before the first 'John'.

However, the pattern I applied seems to replace John from the end to the head. So I need to call sed twice.

How could I find the correct way?

PATTERN="I am John, you are John also"
OUTPUT=$( echo "$PATTERN" | sed -r "s/(^.*)([ \t]*John[ ,\t]*)(.*$)/\1/" )
echo "$OUTPUT"
OUTPUT=$( echo "$OUTPUT" | sed -r "s/(^.*)([ \t]*John[ ,\t]*)(.*$)/\1/" )
echo "$OUTPUT"

My expectation is only call sed one time. Since if "John" appears several times it will be a trouble.

By the procedure above, it will generate output as:

Firstly it matches & trims the word after the final John; then the first John.

I am John, you are

I am

I want to execute one time and get

I am

Following sed may help you on same.

echo "I am John, you are John also" | sed 's/ John.*//'

Or with variables.

pattern="I am John, you are John also"
output=$(echo "$pattern" | sed 's/John.*//')

Another way of doing it is to use the grep command in Perl mode:

echo "I am John, you are John also" | grep -oP '^(?:(?!John).)*';
I am 
#there will be a space at the end
echo "I am John, you are John also" | grep -oP '^(?:(?!John).)*(?=\s)';
I am
#there is no space at the end

Regex explanations:

^(?:(?!John).)*

This will accept all characters from the beginning of the lines until it reaches the first John .

Regex demo

Awk solution:

s="I am John, you are John also and there is another John there"
awk '{ sub(/[[:space:]]+John.*/, "") }1' <<<"$s"

The output:

I am

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM