Nếu bạn đang sử dụng Bash, bạn thậm chí không phải sử dụng grep
:
files="*.jpg"
regex="[0-9]+_([a-z]+)_[0-9a-z]*"
for f in $files
do
if [[ $f =~ $regex ]]
then
name="${BASH_REMATCH[1]}"
echo "${name}.jpg" # concatenate strings
name="${name}.jpg" # same thing stored in a variable
else
echo "$f doesn't match" >&2 # this could get noisy if there are a lot of non-matching files
fi
done
Nó tốt hơn để đưa các regex trong một biến. Một số mẫu sẽ không hoạt động nếu được bao gồm theo nghĩa đen.
Điều này sử dụng =~
là toán tử đối sánh regex của Bash. Kết quả của trận đấu được lưu vào một mảng gọi là $BASH_REMATCH
. Nhóm chụp đầu tiên được lưu trữ trong chỉ mục 1, nhóm thứ hai (nếu có) trong chỉ mục 2, vv Chỉ số 0 là toàn bộ kết quả.
Bạn nên biết rằng nếu không có neo, regex này (và một trong những sử dụng grep
) sẽ phù hợp với bất kỳ ví dụ sau đây và nhiều hơn nữa, mà có thể không được những gì bạn đang tìm kiếm:
123_abc_d4e5
xyz123_abc_d4e5
123_abc_d4e5.xyz
xyz123_abc_d4e5.xyz
Để loại bỏ các ví dụ thứ hai và thứ tư, hãy regex của bạn như thế này:
^[0-9]+_([a-z]+)_[0-9a-z]*
mà nói rằng chuỗi phải bắt đầu với một hoặc nhiều chữ số. Carat đại diện cho sự bắt đầu của chuỗi. Nếu bạn thêm một dấu đô la vào cuối regex, như thế này:
^[0-9]+_([a-z]+)_[0-9a-z]*$
sau đó ví dụ thứ ba cũng sẽ được loại bỏ kể từ khi chấm không là một trong những nhân vật trong regex và ký hiệu đô la đại diện cuối chuỗi. Lưu ý rằng ví dụ thứ tư cũng không khớp được.
Nếu bạn có GNU grep
(khoảng 2,5 hoặc sau đó, tôi nghĩ rằng, khi các nhà điều hành \K
đã được bổ sung):
name=$(echo "$f" | grep -Po '(?i)[0-9]+_\K[a-z]+(?=_[0-9a-z]*)').jpg
Các \K
điều hành (chiều dài thay đổi nhìn đằng sau) gây ra các mô hình trước để phù hợp với , nhưng không bao gồm kết quả phù hợp trong kết quả. Độ dài tương đương cố định là (?<=)
- mẫu sẽ được bao gồm trước dấu ngoặc đơn đóng. Bạn phải sử dụng \K
nếu số lượng có thể khớp với các chuỗi có độ dài khác nhau (ví dụ: +
, *
, {2,4}
).
Toán tử (?=)
khớp với các mẫu cố định hoặc có độ dài thay đổi và được gọi là "nhìn về phía trước". Nó cũng không bao gồm chuỗi phù hợp trong kết quả.
Để làm cho khớp không phân biệt chữ hoa chữ thường, toán tử (?i)
được sử dụng. Nó ảnh hưởng đến các mô hình theo nó để vị trí của nó là đáng kể.
Regex có thể cần được điều chỉnh tùy thuộc vào việc có các ký tự khác trong tên tệp hay không. Bạn sẽ lưu ý rằng trong trường hợp này, tôi hiển thị một ví dụ về ghép nối một chuỗi cùng một lúc mà chuỗi con được bắt giữ.
Là grep * thực sự * unix tinh khiết hơn sed? –
Ah, không có ý muốn đề nghị điều đó. Tôi chỉ hy vọng rằng một giải pháp có thể được tìm thấy bằng cách sử dụng một công cụ tôi đặc biệt đang cố gắng tìm hiểu ở đây. Nếu không thể giải quyết bằng 'grep', thì' sed' sẽ tuyệt vời, nếu có thể giải quyết bằng cách sử dụng 'sed'. – Isaac
Tôi cần phải đặt một :) trên btw đó ... –