Tìm chuỗi trong khi biết một phần của nó và trả về chuỗi


9

Tôi có một chuỗi, ví dụ

"Icecream123 AirplaneBCD CompanyTL1 ComputerYU1"

Hãy nói rằng tôi biết rằng chuỗi của tôi sẽ chứa chắc chắn chuỗi con IceCream nhưng tôi không biết điều gì xảy ra sau chuỗi đó.

Nó có thể là 123 như trong ví dụ của tôi hoặc nó có thể là một cái gì đó khác nhau.

Trong khi tôi có thể sử dụng grep để phát hiện xem chuỗi con "Icecream" có tồn tại trong chuỗi của tôi bằng lệnh sau không

echo $string | grep -oF 'Icecream';

Cái nào sẽ in

Icecream

Tôi muốn với một lệnh để có được nó để in toàn bộ chuỗi con, trong ví dụ của tôi là

Icecream123

Tất nhiên những gì diễn ra sau Icecream là ngẫu nhiên và không được biết trước vì vậy tôi không thể làm

$SUBSTRING=$(echo $string | grep -oF 'Icecream')
$SUBSTRINGTRAIL=123
echo $SUBSTRING$SUBSTRINGTRAIL

chuỗi con cố định / tĩnh - luôn là "Icecream" hay là biến?
Jeff Schaller

một không gian chỉ ra sự kết thúc của hậu tố mong muốn?
Jeff Schaller

@JeffSchaller Đáng buồn thay, tôi không biết điều đó. Tôi thực sự nhận được một đầu ra đa dòng từ một lệnh khác, mà tôi lưu trữ trong một biến, biến này là chuỗi $ của tôi, khi nó được lặp lại, nó sẽ hiển thị đầu ra đa dòng dưới dạng một dòng có dấu cách giữa chúng. Tôi thực sự không biết đó là một không gian hay một nhân vật đặc biệt như LF. Tôi nghĩ rằng đó là không gian.
Sonamor

Ý tôi là, ví dụ, Icecream123 AirplaneBCDbạn muốn dừng lại ở 123. Đó là bởi vì có một không gian sau 3, hay cái gì khác?
Jeff Schaller

1
Nếu bạn không chắc dữ liệu của mình là gì, thật khó để viết một giải pháp thích hợp. Tất cả các câu trả lời cho đến nay đều cho rằng dữ liệu của bạn nằm trên một dòng, giống như bạn đã hiển thị nó. Tôi đã cố gắng tìm hiểu xem dấu phân cách của bạn là gì - nơi phần "dấu" sẽ dừng lại.
Jeff Schaller

Câu trả lời:


15

Nếu grephỗ trợ của bạn biểu thức chính quy tương thích perl, bạn có thể kết hợp không tham lam với ranh giới từ tiếp theo:

echo "$string" | grep -oP 'Icecream.*?\b'

Mặt khác, khớp chuỗi ký tự không trống dài nhất:

echo "$string" | grep -o 'Icecream[^[:blank:]]*'

Hoặc giữ mọi thứ trong vỏ và xóa chuỗi ký tự dài nhất bắt đầu bằng khoảng trắng:

echo "${string%% *}"

2
Đối với PCRE, tôi sẽ sử dụng 'Icecream\S+'cho một số ký tự không trống.
glenn jackman

Cảm ơn ý kiến ​​của bạn, thật đáng buồn là có vẻ như phiên bản grep của tôi không hỗ trợ regl perl. Bạn có thể thêm một số chi tiết về tùy chọn thứ ba của bạn? Tôi không chắc chắn làm thế nào để thực hiện nó.
Sonamor

Sau một số thử nghiệm nữa, dường như sử dụng echo "$ string" | grep -oP 'Icecream. *? \ b' hoặc 'Icecream \ S +' nó thực hiện công việc. Cảm ơn
Sonamor

thật khó hiểu khi mặc dù biến chuỗi $ của bạn là một chuỗi bạn vẫn phải đặt nó giữa các dấu ngoặc kép!
Sonamor

@Sonamor trong trường hợp này việc trích dẫn là không thực sự cần thiết; tuy nhiên có rất nhiều trường hợp đó một thói quen tốt để có được vào. Xem ví dụ Khi nào cần trích dẫn kép?
Steeldo

7

Sử dụng một grepcái mà biết về -o:

$ printf '%s\n' "$string" | grep -o '\<Icecream[^[:blank:]]*'
Icecream123

Mẫu \<Icecream[^[:blank:]]*phù hợp với chuỗi Icecream(trong đó ký tự Iđứng trước ký tự không phải từ hoặc bắt đầu của dòng) theo sau là 0 hoặc nhiều khoảng trống (không phải khoảng trắng hoặc tab).


Sử dụng awk:

$ printf '%s\n' "$string" | awk -v RS=' ' '/^Icecream/'       
Icecream123

Các awkchương trình chia chuỗi thành hồ sơ không gian tách ra, và kiểm tra mỗi một. Nó sẽ in những cái bắt đầu bằng chuỗi Icecream.

Sử dụng mawkhoặc GNU awk, bạn cũng có thể sử dụng

printf '%s\n' "$string" | awk -v RS='[[:blank:]]' '/^Icecream/'

vì chúng xen RSvào như một biểu thức chính quy nếu nó chứa nhiều hơn một ký tự.


Với sed, theo cách tương tự như với grep:

$ printf '%s\n' "$string" | sed 's/.*\(\<Icecream[^[:blank:]]*\).*/\1/'
Icecream123

Sử dụng /bin/sh:

set -- Icecream123 AirplaneBCD CompanyTL1 ComputerYU1
for string; do
    case $string in
        Icecream*)
            printf '%s\n' "$string"
            break
    esac
done

Perl (với một chút trợ giúp từ tr):

$ printf '%s\n' "$string" | tr ' ' '\n' | perl -ne '/Icecream\S*/ && print'
Icecream123

hoặc chỉ

$ printf '%s\n' "$string" | perl -ne '/(Icecream\S*)/ && print $1, "\n"'
Icecream123

Hoặc, chia thành các dòng và khớp với khóa:echo "$string" | grep -o '\S\+' | grep "Icecream"
Isaac

7

Vì bạn đã gắn thẻ bash:

[[ $string =~ (Icecream[^ ]*) ]] && result=${BASH_REMATCH[1]}

Tổng quát hơn, cho một cụm từ tìm kiếm trong $search:

[[ $string =~ ($search[^ ]*) ]] && result=${BASH_REMATCH[1]}

... hoặc với mở rộng tham số:

# remove any leading text up to -and through- the search text:
x=${string##*$search}

# remove any trailing space onwards
result=$search${x%% *}

2

Ví dụ: nếu bạn sử dụng GNU grep:

$ echo "Icecream123 AirplaneBCD CompanyTL1 ComputerYU1" | grep -oP '\bIcecream.*?(\s|$)' --color

Nó sử dụng PCRE.


1

Có lẽ đơn giản hơn một chút, đặc biệt là khi bạn nói rằng phiên bản grep của bạn không hỗ trợ regl perl:

$ echo $string | tr ' ' '\n' | grep 'Icecream' Icecream123

Việc trchia chuỗi thành các dòng bằng cách thay thế tất cả các khoảng trắng bằng dòng mới. Sau đó, bạn có thể sử dụng grepdễ dàng.

Bạn cũng có thể viết những điều sau để chỉ lấy những gì theo từ bạn đang tìm kiếm:

$ echo $string | tr ' ' '\n' | sed -n 's/Icecream//p' 123

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.