Tách chuỗi bởi lần xuất hiện đầu tiên của dấu phân cách


54

Tôi có một chuỗi ở định dạng tiếp theo

id;some text here with possible ; inside

và muốn tách nó thành 2 chuỗi bởi lần xuất hiện đầu tiên của ;. Vì vậy, nó nên là: idsome text here with possible ; inside

Tôi biết cách chia chuỗi (ví dụ, với cut -d ';' -f1), nhưng nó sẽ chia thành nhiều phần hơn vì tôi có ;bên trong phần bên trái.


Sau khi chuỗi được chia, bạn muốn làm gì với "id"? Bạn có muốn gán nó cho một biến, in nó ra, vv?
Daemon of Chaos

Tôi sẽ có 2 biến: idstring
gakhov

Câu trả lời:


65

cut Nghe có vẻ là một công cụ phù hợp cho việc này:

bash-4.2$ s='id;some text here with possible ; inside'

bash-4.2$ id="$( cut -d ';' -f 1 <<< "$s" )"; echo "$id"
id

bash-4.2$ string="$( cut -d ';' -f 2- <<< "$s" )"; echo "$string"
some text here with possible ; inside

Nhưng readthậm chí còn phù hợp hơn:

bash-4.2$ IFS=';' read -r id string <<< "$s"

bash-4.2$ echo "$id"
id

bash-4.2$ echo "$string"
some text here with possible ; inside

3
Tuyệt quá! Nó hoạt động như một say mê! Tôi sẽ chọn readvì tôi đang sử dụng bash. Cảm ơn bạn @manatwork!
gakhov

Cách cuttiếp cận sẽ chỉ hoạt động khi "$ s" không chứa các ký tự dòng mới. đọc là trong bất kỳ vỏ giống như Bourne. <<< là trong RC, zsh và các phiên bản gần đây của bash và ksh93 và là phiên bản không chuẩn.
Stéphane Chazelas

Rất tiếc, bạn đã đúng @StephaneChazelas. Tâm trí của tôi tại -ađối với một số lý do khi nhắc đến bash's read. (Rõ ràng là không sử dụng ở đây.)
manatwork

Tôi quên đề cập rằng phương pháp đọc không hoạt động nếu $ s chứa các ký tự dòng mới. Tôi đã thêm câu trả lời của riêng mình.
Stéphane Chazelas

1
Tôi muốn nhấn mạnh dấu gạch ngang trailing ở -f 2-trong string="$( cut -d ';' -f 2- <<< "$s" )"; echo "$string"lệnh. Đây là những gì bỏ qua phần còn lại của các dấu phân cách trong chuỗi cho bản in. Không rõ ràng khi nhìn vào trang người đàn ông củacut
Steen

17

Với bất kỳ sh tiêu chuẩn nào (bao gồm cả bash):

sep=';'
case $s in
  (*"$sep"*)
    before=${s%%"$sep"*}
    after=${s#*"$sep"}
    ;;
  (*)
    before=$s
    after=
    ;;
esac

readcác giải pháp dựa trên sẽ hoạt động cho các ký tự đơn (và với một số giá trị shell, byte đơn) $sepkhác với không gian, tab hoặc dòng mới và chỉ khi $skhông chứa các ký tự dòng mới.

cutgiải pháp dựa trên sẽ chỉ hoạt động nếu $skhông chứa các ký tự dòng mới.

sedcác giải pháp có thể được nghĩ ra để xử lý tất cả các trường hợp góc với bất kỳ giá trị nào $sep, nhưng không đáng để đi xa đến mức khi có hỗ trợ dựng sẵn trong vỏ cho điều đó.


6

Như bạn đã đề cập rằng bạn muốn gán các giá trị cho idchuỗi

đầu tiên gán mẫu của bạn cho một biến (nói str)

    str='id;some text here with possible ; inside'
    id=${str%%;} 
    string=${str#;}

Bây giờ bạn có giá trị của bạn trong các biến tương ứng


nếu bạn nhận được mẫu của mình từ một lệnh thì hãy sử dụng set - some_command, thì mẫu của bạn sẽ được lưu trữ trong $ 1 và sử dụng mã ở trên với 1 thay vì str
user1678213

Câu trả lời này khác với @StephaneChazelas như thế nào?
Bernhard

4

Ngoài các giải pháp khác, bạn có thể thử một cái gì đó regexdựa trên:

a="$(sed 's/;.*//' <<< "$s")"
b="$(sed 's/^[^;]*;//' <<< "$s")"

hoặc tùy thuộc vào những gì bạn đang cố gắng làm chính xác, bạn có thể sử dụng

sed -r 's/^([^;]*);(.*)/\1 ADD THIS TEXT BETWEEN YOUR STRINGS \2/'

nơi \1\2chứa hai chuỗi con bạn muốn.


1

Giải pháp trong bash tiêu chuẩn:

    text='id;some text here with possible ; inside'
    text2=${text#*;}
    text1=${text%"$text2"}

    echo $text1
    #=> id;
    echo $text2
    #=> some text here with possible ; insideDD
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.