Định dạng đầu ra của xargs


10

Tôi muốn thay đổi định dạng của màn hình xargs đầu ra

cat k.txt 
1 
2 
3 

cat k.txt | xargs 
1 2 3

Tuy nhiên tôi muốn có 1, 2, 3hoặc 1|2|3. Bất kỳ đề xuất?


Điều đó có thể đạt được với một cái gì đó (không chính xác này) giống như xargs cat -n, nhưng là dễ dàng hơn nếu bạn chỉ cần cắt các nhân vật xuống dòng, điều này có thể đạt được với echo $(cat), grephoặc awk(crawl cách để làm điều đó). xargskhông phù hợp với mục đích hiện tại của bạn.
41754

Câu trả lời:


18

Dưới đây là một tá ví dụ về cách bạn có thể lấy một tệp như thế này:

$ cat k.txt
1
2
3

và chuyển đổi nó sang định dạng này:

1,2,3

Bạn có thể sử dụng lệnh này để tạo tệp trên nếu bạn muốn chơi cùng:

$ cat <<EOF > k.txt
1
2
3
EOF

Các ví dụ dưới đây được chia thành 2 nhóm. Những người "làm việc" và những người "gần như" làm việc. Tôi bỏ những thứ này bởi vì thường thì nó rất có giá trị để xem tại sao một cái gì đó không hoạt động, vì nó là để xem tại sao một cái gì đó làm.

Hầu hết các ngôn ngữ kịch bản mà tôi quen thuộc được trình bày. Một số được biểu diễn nhiều lần, vì như với từ viết tắt nổi tiếng thường được tham chiếu trong Perl, TIMTOWTDI .

LƯU Ý: Bạn có thể hoán đổi dấu phẩy ( ,) trong các ví dụ bên dưới và thay thế nó bằng bất kỳ ký tự nào bạn muốn, nghĩa là |.

Ví dụ "làm việc"

Các đoạn mã này sẽ tạo ra đầu ra mong muốn.

Các pastelệnh:

$ paste -s -d ',' k.txt 
1,2,3

Các sedlệnh:

$ sed ':a;N;$!ba;s/\n/,/g' k.txt
1,2,3

$ sed ':a;{N;s/\n/,/};ba' k.txt 
1,2,3

Các perllệnh:

$ perl -00 -p -e 's/\n(?!$)/,/g' k.txt
1,2,3

$ perl -00 -p -e 'chomp;tr/\n/,/' k.txt
1,2,3

Các awklệnh:

$ awk '{printf"%s%s",c,$0;c=","}' k.txt
1,2,3

$ awk '{printf "%s,",$0}' k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

$ awk -vORS=, 1 k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

$ awk 'BEGIN {RS="dn"}{gsub("\n",",");print $0}' k.txt | awk '{sub(/\,$/,"");print}'
1,2,3

Các pythonlệnh:

$ python -c "import sys; print sys.stdin.read().replace('\n', ',')[0:-1]" <k.txt
1,2,3

$ python -c "import sys; print sys.stdin.read().replace('\n', ',').rstrip(',')" <k.txt
1,2,3

Bash's tích mapfilehợp:

$ mapfile -t a < k.txt; (IFS=','; echo "${a[*]}")
1,2,3

Các rubylệnh:

$ ruby -00 -pe 'gsub /\n/,",";chop' < k.txt
1,2,3

$ ruby -00 -pe '$_.chomp!"\n";$_.tr!"\n",","' k.txt
1,2,3

Các phplệnh:

$ php -r 'echo strtr(chop(file_get_contents($argv[1])),"\n",",");' k.txt
1,2,3

Hãy cẩn thận

Hầu hết các ví dụ trên sẽ hoạt động tốt. Một số có các vấn đề ẩn, chẳng hạn như ví dụ PHP ở trên. Hàm chop()thực sự là một bí danh rtrim(), do đó, các dấu cách của dòng cuối cùng cũng sẽ bị xóa.

Ví dụ về Ruby đầu tiên và ví dụ Python đầu tiên cũng vậy. Vấn đề là làm thế nào tất cả họ sử dụng một loại hoạt động mà về cơ bản là "cắt xén", một cách mù quáng, một nhân vật dấu vết. Điều này tốt đối với ví dụ mà OP cung cấp, nhưng phải cẩn thận khi sử dụng các loại một lớp lót này để đảm bảo rằng chúng phù hợp với dữ liệu mà chúng đang xử lý.

Thí dụ

Nói tập tin mẫu của chúng tôi, k.txttrông giống như thế này:

$ echo -en "1\n2\n3" > k.txt

Nó trông tương tự nhưng nó có một sự khác biệt nhỏ. Nó không có một dòng mới ( \n) như tệp gốc. Bây giờ khi chúng ta chạy ví dụ Python đầu tiên, chúng ta sẽ nhận được điều này:

$ python -c "import sys; print sys.stdin.read().replace('\n', ',')[0:-1]" <k.txt
1,2,

Ví dụ "gần như" hoạt động

Đây là những ví dụ "luôn luôn là phù dâu, không bao giờ là cô dâu" . Hầu hết trong số họ có thể có thể thích nghi, nhưng khi thực hiện một giải pháp tiềm năng cho một vấn đề, khi cảm thấy "bị ép buộc", đó có lẽ là công cụ sai cho công việc!

Các perllệnh:

$ perl -p -e 's/\n/,/' k.txt
1,2,3,

Các trlệnh:

$ tr '\n' ','  < k.txt 
1,2,3,

Các lệnh cat+ echo:

$ echo $(cat k.txt)
1 2 3

Các rubylệnh:

$ ruby -pe '$_["\n"]=","' k.txt
1,2,3,

Bash's while+ readdựng sẵn:

$ while read line; do echo -n "$line,"; done < k.txt
1,2,3,

1
Về awktôi thích một sự thay thế ngắn hơn:awk -vORS=, 1 k.txt
manatwork

Không chắc chắn liệu CentOS có bash:mapfile -t a < k.txt; (IFS=','; echo "${a[*]}")
manatwork

không chắc chắn về dòng mới. Theo thử nghiệm của tôi perlvà đầu tiên của bạn cũng awkcó chúng.
manatwork

Tôi sẽ đặt pastecái ở trên cùng. Đó chính xác paste -slà những gì dành cho đây. Đó là một lệnh tiêu chuẩn và sẽ hiệu quả nhất. Tất cả những cái khác là quá mức cần thiết và / hoặc không thể mang theo hoặc có những hạn chế.
Stéphane Chazelas

mapfilelà tương đối mới, được thêm vào bash4.0.
manatwork

4

@slm đã đưa ra câu trả lời hay, nhưng như câu hỏi của bạn "định dạng đầu ra của xargs"

xargs -I{} echo -n "{}|" < test.txt
  • -I là tùy chọn "thay thế chuỗi".
  • {} là một giữ chỗ cho văn bản đầu ra.
  • Điều này tương tự với việc sử dụng cặp ngoặc nhọn trong "find".

Nếu bạn muốn thoát khỏi dấu vết, |bạn có thể sử dụng sedđể dọn dẹp:

$ xargs -I{} echo -n "{}|" < k.txt  | sed -e 's/|$//'
1|2|3

Điều đó giải quyết một đường ống phụ vào sau 3. "1 | 2 | 3 |". Tôi đã có cùng một vấn đề với một giải pháp vòng lặp và awk.
slm

vâng, nếu có dòng mới .. tr, sedvà cũng có dòng khác ..
Rahul Patil

2

Đây là một chủ đề cũ, tôi biết. OP đã hỏi với một mã đơn giản như thế này. Để giữ cho nó gần với bản gốc, tôi có một giải pháp đơn giản.

cat k.txt | xargs
1 2 3

sử dụng sed

cat k.txt | xargs | sed 's/ /,/g'
1,2,3

hoặc là

cat k.txt | xargs | sed 's/ /|/g'
1|2|3

sed có thể trông hơi kỳ lạ nhưng bị phá vỡ, nó có ý nghĩa nhiều.

Là để thay thế. g 'là dành cho toàn cầu: không có cái này, nó sẽ chỉ thay thế đầu tiên trên mỗi dòng mới. Vì bạn sử dụng 'xargs', nó sẽ hiển thị chúng dưới dạng một dòng. Vì vậy, bạn sẽ nhận được "1,2 3".

Dấu phân cách được sử dụng để phân tách. Tôi đã sử dụng / ký tự. Một mẹo thú vị: bạn có thể thay thế dấu phân cách bằng hầu hết mọi ký tự khác, miễn là chúng tôi giữ nguyên định dạng giữa các dấu ngoặc kép. Vì vậy, điều này cũng sẽ làm việc ....

cat k.txt | xargs | sed 's# #,#g'

hoặc là

cat k.txt | xargs | sed 'sT T,Tg'

Rõ ràng, sử dụng một số ký tự nhất định làm dấu phân cách có thể gây nhầm lẫn, vì vậy hãy thông minh.


0
xargs <k.txt | tr \  \|

Bạn không cần phải cat- chỉ cần vượt qua trong các tập tin đầu vào và - nếu được lệnh không có khác - xargssẽ ngất xỉu định dạng mặc định của nó - đó là một loại với /bin/echo's (không có giải thích xuyệc ngược c-thoát) .

xargssẽ loại bỏ khoảng trắng đầu / đuôi khỏi tệp đầu vào và nén các chuỗi khoảng trắng khác xuống một khoảng trống. Điều này có nghĩa là trong khi chuyển tệp từ trsang xargsthích:

tr \\n \| <k.txt | xargs

... bản in ...

1|2|3|

... đi theo cách khác và chỉ hoạt động trên args rằng xargskhông gian delimits không ....

1|2|3\n

... bởi vì xargsin dòng mới cuối cùng (như được yêu cầu cho một tệp văn bản) , nhưng nó không bị trlỗi theo cách đó.

Tuy nhiên, lưu ý rằng điều này (hoặc bất kỳ giải pháp nào khác được cung cấp ở đây) không tính đến việc xargstrích dẫn trong đầu vào. xargssẽ bỏ qua các ký tự khoảng trắng không phải dòng mới được trích dẫn theo nghĩa đen trong đầu vào, có thể được trích dẫn như sau:

xargs <<\IN
1    2'      3'\'      \'4
IN

1 2      3' '4
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.