tra-loi-cau-hoi-phat-trien-web.com

Làm thế nào để hợp nhất mỗi hai dòng thành một từ dòng lệnh?

Tôi có một tập tin văn bản với định dạng sau. Dòng đầu tiên là "KEY" và dòng thứ hai là "GIÁ TRỊ".

KEY 4048:1736 string
3
KEY 0:1772 string
1
KEY 4192:1349 string
1
KEY 7329:2407 string
2
KEY 0:1774 string
1

Tôi cần giá trị trong cùng dòng với khóa. Vì vậy, đầu ra sẽ trông như thế này ...

KEY 4048:1736 string 3
KEY 0:1772 string 1
KEY 4192:1349 string 1
KEY 7329:2407 string 2
KEY 0:1774 string 1

Sẽ tốt hơn nếu tôi có thể sử dụng một số dấu phân cách như $ hoặc ,:

KEY 4048:1736 string , 3

Làm cách nào để hợp nhất hai dòng thành một?

122
shantanuo

ôi

awk 'NR%2{printf "%s ",$0;next;}1' yourFile

lưu ý, có một dòng trống ở cuối đầu ra.

sed:

sed 'N;s/\n/ /' yourFile
148
Kent

paste tốt cho công việc này:

paste -d " "  - - < filename
205
glenn jackman

Thay thế cho sed, awk, grep:

xargs -n2 -d'\n'

Điều này là tốt nhất khi bạn muốn tham gia N dòng và bạn chỉ cần đầu ra được phân tách không gian.

Câu trả lời ban đầu của tôi là xargs -n2 phân tách trên các từ thay vì các dòng. -d có thể được sử dụng để phân chia đầu vào theo bất kỳ ký tự đơn nào.

29
nnog

Có nhiều cách để giết một con chó hơn là treo cổ. [1]

awk '{key=$0; getline; print key ", " $0;}'

Đặt bất cứ dấu phân cách nào bạn thích bên trong dấu ngoặc kép.


Tài liệu tham khảo:

  1. Ban đầu "Rất nhiều cách để lột da con mèo", trở lại với một biểu hiện già hơn, có khả năng bắt nguồn từ vật nuôi.
25
ghoti

Đây là một cách khác với awk:

awk 'ORS=NR%2?FS:RS' file
$ cat file
KEY 4048:1736 string
3
KEY 0:1772 string
1
KEY 4192:1349 string
1
KEY 7329:2407 string
2
KEY 0:1774 string
1
$ awk 'ORS=NR%2?FS:RS' file
KEY 4048:1736 string 3
KEY 0:1772 string 1
KEY 4192:1349 string 1
KEY 7329:2407 string 2
KEY 0:1774 string 1

Như được chỉ ra bởi Ed Morton trong các bình luận, tốt hơn là thêm niềng răng cho an toàn và parens cho tính di động.

awk '{ ORS = (NR%2 ? FS : RS) } 1' file

ORS là viết tắt của Dấu tách bản ghi đầu ra. Những gì chúng tôi đang làm ở đây là kiểm tra một điều kiện bằng cách sử dụng NR lưu số dòng. Nếu modulo của NR là một giá trị thực (> 0) thì chúng ta đặt Dấu tách trường đầu ra thành giá trị của FS (Dấu tách trường) theo mặc định là khoảng trắng, nếu không, chúng ta sẽ gán giá trị của RS (Dấu tách bản ghi) là dòng mới.

Nếu bạn muốn thêm , làm dấu phân cách thì hãy sử dụng như sau:

awk '{ ORS = (NR%2 ? "," : RS) } 1' file
11
jaypal singh

Đây là giải pháp của tôi trong bash:

while read line1; do read line2; echo "$line1, $line2"; done < data.txt
10
Hai Vu

Mặc dù có vẻ như các giải pháp trước đó sẽ hoạt động, nếu một sự bất thường duy nhất xảy ra trong tài liệu, đầu ra sẽ chuyển thành từng mảnh. Dưới đây là một chút an toàn hơn.

sed -n '/KEY/{
N
s/\n/ /p
}' somefile.txt
10
J.D.

"ex" là một trình soạn thảo dòng có thể viết được trong cùng một gia đình như sed, awk, grep, v.v. Tôi nghĩ đó có thể là những gì bạn đang tìm kiếm. Nhiều bản sao/người kế vị hiện đại cũng có chế độ vi.

 ex -c "%g/KEY/j" -c "wq" data.txt

Điều này nói cho mỗi dòng, nếu nó khớp với "KEY" thì thực hiện một j oin của dòng sau. Sau khi lệnh đó hoàn thành (đối với tất cả các dòng), đưa ra một w rite và q uit.

7
Justin

Bạn có thể sử dụng awk như thế này để kết hợp 2 cặp dòng:

awk '{ if (NR%2 != 0) line=$0; else {printf("%s %s\n", line, $0); line="";} } \
     END {if (length(line)) print line;}' flle
4
anubhava

Nếu Perl là một tùy chọn, bạn có thể thử:

Perl -0pe 's/(.*)\n(.*)\n/$1 $2\n/g' file.txt
4
andrefs

Một biến thể nhỏ trên câu trả lời của glenn jackman bằng cách sử dụng paste: nếu giá trị cho tùy chọn dấu phân cách -d chứa nhiều hơn một ký tự, thì paste sẽ chuyển qua từng ký tự một và kết hợp với các tùy chọn -s xử lý cùng một tập tin đầu vào.

Điều này có nghĩa là chúng ta có thể sử dụng bất cứ thứ gì chúng ta muốn có như dấu phân cách cộng với chuỗi thoát \n để hợp nhất hai dòng cùng một lúc.

Sử dụng dấu phẩy:

$ paste -s -d ',\n' infile
KEY 4048:1736 string,3
KEY 0:1772 string,1
KEY 4192:1349 string,1
KEY 7329:2407 string,2
KEY 0:1774 string,1

và ký hiệu đô la:

$ paste -s -d '$\n' infile
KEY 4048:1736 string$3
KEY 0:1772 string$1
KEY 4192:1349 string$1
KEY 7329:2407 string$2
KEY 0:1774 string$1

Điều này không thể làm là sử dụng dấu phân cách bao gồm nhiều ký tự.

Như một phần thưởng, nếu paste tuân thủ POSIX, điều này sẽ không sửa đổi dòng mới của dòng cuối cùng trong tệp, do đó, đối với một tệp đầu vào có số lượng dòng lẻ như

KEY 4048:1736 string
3
KEY 0:1772 string

paste sẽ không xử lý ký tự phân tách ở dòng cuối cùng:

$ paste -s -d ',\n' infile
KEY 4048:1736 string,3
KEY 0:1772 string
3
Benjamin W.

Bạn cũng có thể sử dụng lệnh vi sau:

:%g/.*/j
3
Jdamian
nawk '$0 ~ /string$/ {printf "%s ",$0; getline; printf "%s\n", $0}' filename

Cái này đọc là

$0 ~ /string$/  ## matches any lines that end with the Word string
printf          ## so print the first line without newline
getline         ## get the next line
printf "%s\n"   ## print the whole line and carriage return
1
Shahab Khan

Một giải pháp khác sử dụng vim (chỉ để tham khảo).

Giải pháp 1:

Mở tệp trong vim vim filename, sau đó thực thi lệnh :% normal Jj

Lệnh này được bỏ dễ hiểu:

  • %: cho tất cả các dòng,
  • bình thường: thực hiện lệnh bình thường
  • Jj: thực hiện lệnh Tham gia, sau đó nhảy xuống dòng bên dưới

Sau đó, lưu tệp và thoát bằng :wq

Giải pháp 2:

Thực hiện lệnh trong Shell, vim -c ":% normal Jj" filename, sau đó lưu tệp và thoát bằng :wq.

1
Jensen

Trong trường hợp tôi cần kết hợp hai dòng (để xử lý dễ dàng hơn), nhưng cho phép dữ liệu vượt quá mức cụ thể, tôi thấy điều này hữu ích

data.txt

string1=x
string2=y
string3
string4
cat data.txt | nawk '$0 ~ /string1=/ { printf "%s ", $0; getline; printf "%s\n", $0; getline } { print }' > converted_data.txt

đầu ra sau đó trông như:

convert_data.txt

string1=x string2=y
string3
string4
1
Ben Taylor

Cách đơn giản nhất là ở đây:

  1. Xóa các dòng chẵn và viết nó trong một số tệp tạm thời 1.
  2. Xóa các dòng lẻ và viết nó trong một số tệp tạm thời 2.
  3. Kết hợp hai tệp trong một bằng cách sử dụng lệnh dán với -d (có nghĩa là xóa khoảng trắng)
sed '0~2d' file > 1 && sed '1~2d' file > 2 && paste -d " " 1 2
0
Serg
Perl -0pE 's{^KEY.*?\K\s+(\d+)$}{ $1}msg;' data.txt > data_merged-lines.txt

-0 ngấu nghiến toàn bộ tập tin thay vì đọc từng dòng một;
[.__.] pE bọc mã bằng vòng lặp và in kết quả đầu ra, xem chi tiết trong http://perldoc.Perl.org/perlrun.html ;
[.__.] ^KEY khớp "KEY" ở đầu dòng, theo sau là kết hợp không tham lam của bất cứ thứ gì (.*?) trước chuỗi

  1. một hoặc nhiều khoảng trắng \s+ thuộc bất kỳ loại nào kể cả ngắt dòng;
  2. một hoặc nhiều chữ số (\d+) mà chúng tôi chụp và sau đó chèn lại dưới dạng $1;

theo sau là cuối dòng $.

\K thuận tiện loại trừ mọi thứ ở phía bên trái của nó khỏi sự thay thế, vì vậy { $1} chỉ thay thế 1-2 chuỗi, xem http://perldoc.Perl.org/perlre.html .

0
Onlyjob

Một giải pháp tổng quát hơn (cho phép nhiều hơn một dòng tiếp theo được tham gia) dưới dạng tập lệnh Shell. Điều này thêm một dòng giữa mỗi, bởi vì tôi cần tầm nhìn, nhưng điều đó dễ dàng được khắc phục. Ví dụ này là nơi dòng "chìa khóa" kết thúc: và không có dòng nào khác làm được.

#!/bin/bash
#
# join "The rest of the story" when the first line of each   story
# matches $PATTERN
# Nice for looking for specific changes in bart output
#

PATTERN='*:';
LINEOUT=""
while read line; do
    case $line in
        $PATTERN)
                echo ""
                echo $LINEOUT
                LINEOUT="$line"
                        ;;
        "")
                LINEOUT=""
                echo ""
                ;;

        *)      LINEOUT="$LINEOUT $line"
                ;;
    esac        
done
0
Jan Parcel