2011-10-11 37 views
31

Tôi muốn nhúng một lệnh dài như thế này trong một kịch bản bash:Làm cách nào để chia nhỏ chuỗi ký tự cực dài trong bash?

mycommand \ 
    --server myserver \ 
    --filename extremely/long/file/name/that/i/would/like/to/be/able/to/break/up/if/possible \ 
    --otherflag \ 
    --anotherflag 

với tên tập tin dài tan rã.

tôi có thể làm điều này:

# Insufficiently pretty 
mycommand \ 
    --server myserver \ 
    --filename extremely/long/file/name/\ 
that/i/would/like/to/be/able/to/break/\ 
up/if/possible \ 
    --otherflag \ 
    --anotherflag \ 

nhưng nó phá vỡ dòng chảy. Tôi sẽ như để có thể viết này:

# Doesn't work 
mycommand \ 
    --server myserver \ 
    --filename extremely/long/file/name/\ 
     that/i/would/like/to/be/able/to/break/\ 
     up/if/possible \ 
    --otherflag \ 
    --anotherflag 

nhưng điều đó không làm việc vì nó sẽ vỡ ra chuỗi chữ.

Có cách nào để yêu cầu bash phá vỡ chuỗi ký tự nhưng bỏ qua bất kỳ dấu cách hàng đầu nào không?

Trả lời

36

Bạn có thể sử dụng một biến:

file=extremely/long/file/name 
file+=/that/i/would/like/to/be/able/to/break 
file+=/up/if/possible 

mycommand\ 
    --server myserver\ 
    --filename $file\ 
    --flag flag 
+6

Ý tưởng hay. Bạn có thể làm cho nó sạch hơn mặc dù, bằng cách sử dụng toán tử '+ =' thay vì 'file = $ {file}/...' – Chriszuma

+5

+1: Đây là cách tiếp cận ít bị làm phiền theo ý kiến ​​của tôi. Mục đích là rõ ràng. –

+0

@Chriszuma Có Tôi quên rằng bash cho phép toán tử '+ ='. Tôi đã chỉnh sửa câu trả lời của mình. – WilQu

36

Đó là một chút của một hack, nhưng công trình này:

mycommand \ 
    --server myserver \ 
    --filename "extremely/long/file/name/"` 
       `"that/i/would/like/to/be/able/to/break/"` 
       `"up/if/possible" \ 
    --otherflag \ 
    --anotherflag 

Bash concatenates xâu đó là liền kề, vì vậy chúng tôi tận dụng điều đó. Ví dụ: echo "hi" "there" in hi there trong khi echo "hi""there" in hithere.

Nó cũng tận dụng lợi thế của toán tử backtick và thực tế là một loạt các không gian được đánh giá là không có gì.

+2

Bạn có thể đặt mở '\' 'ở cuối dòng trước, thay vì' \ 'dòng liên tục ... nó giữ cạnh trái sạch –

+0

Cuộc gọi tốt, không nghĩ về điều đó. Đã chỉnh sửa đúng. – Chriszuma

1

Về cơ bản, không có gì được xây dựng vào bash để làm điều này là.
Một trình bao bọc thường gặp nhiều rắc rối hơn giá trị của nó, nhưng điều đó nói rằng, bạn có thể thử một bí danh hoặc một funciton, ví dụ. j

j(){sed -e ':a;$!N;s/ *\n *//g;ta' <<<"$1"} 

echo "$(j "3 spaces 
      /hello 
      /world 
      /this 
      /is 
      /a 
      /long 
      /path 
      ")" 

# 3 spaces/hello/world/this/is/a/long/path 
3

tôi định nghĩa một hàm strcat ngắn ở phía trên cùng của kịch bản bash tôi và sử dụng một lời gọi nội tuyến để chia mọi thứ lên. Đôi khi tôi thích nó bằng cách sử dụng một biến riêng biệt bởi vì tôi có thể xác định nội dung dài theo dòng với lệnh gọi.

function strcat() { 
    local IFS="" 
    echo -n "$*" 
} 

mycommand \ 
    --server myserver \ 
    --filename "$(strcat \ 
     extremely/long/file/name/ \ 
     that/i/would/like/to/be/able/to/break/ \ 
     up/if/possible)" \ 
    --otherflag \ 
    --anotherflag \ 

Tôi cũng như cách tiếp cận này cho khi tôi phải nhập CSV dài các giá trị như một tham số cờ vì tôi có thể sử dụng nó để tránh gõ dấu phẩy giữa các giá trị:

function strjoin() { 
    local IFS="$1" 
    shift 
    echo -n "$*" 
} 

csv_args=(
    foo=hello 
    bar=world 
    "this=arg has spaces in it" 
) 
mycommand \ 
    --server myserver \ 
    --csv_args "$(strjoin , "${csv_args[@]}")" \ 
    --otherflag \ 
    --anotherflag \ 

Đó là tương đương để

mycommand \ 
    --server myserver \ 
    --csv_args "foo=hello,bar=world,this=arg has spaces in it" \ 
    --otherflag \ 
    --anotherflag \ 
1

Người ta cũng có thể sử dụng một mảng biến

file=(extremely/long/file/name 
    /that/i/would/like/to/be/able/to/break 
    /up/if/possible) 
IFS='' 

echo mycommand\ 
    --server myserver\ 
    --filename "${file[*]}"\ 
    --flag flag 
Các vấn đề liên quan