วิธีการรวมข้อความของบรรทัดที่เป็นตัวอักษรเข้ากับบรรทัดที่เป็นตัวเลขในเชลล์?


10

ฉันมีไฟล์ที่มีข้อความเช่นนี้:

AAAA
BBBB
CCCC
DDDD

1234
5678
9012
3456

EEEE 

7890

ฯลฯ ...

และฉันต้องการจับคู่ตัวอักษรกับบรรทัดตัวเลขเพื่อให้เป็นเช่นนี้:

AAAA 1234 
BBBB 5678
CCCC 9012
DDDD 3456

EEEE 7890

ไม่มีใครรู้วิธีง่ายๆในการบรรลุเป้าหมายนี้หรือไม่?


คุณพูดถึงemacs.. คุณกำลังมองหาelispวิธีการแก้ปัญหาหรือวิธีการเรียกใช้เปลือกสคริปต์จากภายใน emacs?
Peter.O

คำตอบ:


3

วิธีหนึ่งในการใช้perl:

เนื้อหาของscript.pl:

use warnings;
use strict;

## Check arguments.
die qq[Usage: perl $0 <input-file>\n] unless @ARGV == 1;

my (@alpha, @digit);

while ( <> ) {
        ## Omit blank lines.
        next if m/\A\s*\Z/;

        ## Remove leading and trailing spaces.
        s/\A\s*//;
        s/\s*\Z//;

        ## Save alphanumeric fields and fields with
        ## only digits to different arrays.
        if ( m/\A[[:alpha:]]+\Z/ ) {
                push @alpha, $_;
        }
        elsif ( m/\A[[:digit:]]+\Z/ ) {
                push @digit, $_;
        }
}

## Get same positions from both arrays and print them
## in the same line.
for my $i ( 0 .. $#alpha ) {
        printf qq[%s %s\n], $alpha[ $i ], $digit[ $i ];
}

เนื้อหาของinfile:

AAAA
BBBB
CCCC
DDDD

1234
5678
9012
3456

EEEE 

7890

เรียกใช้เช่น:

perl script.pl infile

และผลลัพธ์:

AAAA 1234
BBBB 5678
CCCC 9012
DDDD 3456
EEEE 7890

ที่น่าสนใจ ... สองเส้นเปลี่ยนตัว regex ของคุณซึ่งเอาออกชั้นนำและช่องว่างต่อท้ายทำงานเกี่ยวกับ 1.6 เท่าเร็วกว่าเส้นเดียวที่ใช้ backreferencing s/\A\s*(.*?)\s*\Z/\1/และไม่โลภ:
Peter.O

4

ในawkการรักษาบรรทัดว่างโดยสมมติว่าไฟล์มีรูปแบบที่ดี แต่สามารถเพิ่มตรรกะเพื่อตรวจสอบไฟล์:

awk -v RS="" '{for(i=1; i<=NF; i++) a[i]=$i
  getline
  for(i=1; i<=NF; i++) print a[i] " " $i
  print ""}' file

4
<input sed -nr '/^[A-Z]{4}$/,/^$/w out1
                /^[0-9]{4}$/,/^$/w out2'
paste -d' ' out1 out2 |sed 's/^ $//' 

หรือในขั้นตอนเดียวโดยไม่มีไฟล์ชั่วคราว

paste -d' ' <(sed -nr '/^[A-Z]{4}$/,/^$/p' input) \
            <(sed -nr '/^[0-9]{4}$/,/^$/p' input) | sed 's/^ $//' 

sedขั้นตอนสุดท้ายลบตัวคั่นบนบรรทัดว่างซึ่งแนะนำโดยpaste...


3

ด้วย emacs ใช้การดำเนินการรูปสี่เหลี่ยมผืนผ้าเพื่อตัดบรรทัดข้อความและวางไว้ข้างหน้าบรรทัดตัวเลข


ขอบคุณ แต่ไม่เหมาะสำหรับสายมากกว่า 15,000 รายการ! +1 สำหรับแนวคิดในการทำงานและคุณต้องการตัวแทน :)
NWS

2

หากรายการอยู่ในลำดับ

  1. แยกอินพุตเป็นรายการตัวอักษรและรายการตัวเลขโดยใช้grep:

    • grep "[[:alpha:]]\+" < file > alpha
    • grep "[[:digit:]]\+" < file > digit
  2. เข้าร่วมสองไฟล์ที่ได้alphaและdigitใช้paste:

    • paste alpha digit(คุณสามารถเพิ่ม-d " "เพื่อให้มันใช้พื้นที่แทนแท็บ)

1
โดยไม่ต้องไฟล์ temp: หรือทดแทนกระบวนการเดียว:paste <(grep "[[:alpha:]]\+" file) <(grep "[[:digit:]]\+" file) grep "[[:alpha:]]\+" file | paste - <(grep "[[:digit:]]\+" file)
jfg956

1

awk ที่แย่เกินไปก็ไม่มีฟังก์ชั่น push / pop / unshift / shift ที่ดี นี่เป็นตัวอย่างสั้น ๆ ของ Perl

perl -M5.010 -lne '
  given ($_) {
    when (/^[[:alpha:]]+$/) {push @alpha, $_}
    when (/^\d+$/) {say shift(@alpha), " ", $_}
    default {say}
  }
'

เมื่อฉันเรียกใช้มันจะเพิ่มบรรทัดว่าง (นำหน้า) พิเศษต่อกลุ่ม
Peter.O

เนื่องจากส่วนdefaultคำสั่งจะมีการพิมพ์บรรทัดว่างทันทีดังนั้นช่องว่างก่อน "1234" จะปรากฏก่อนบรรทัด "AAAA"
เกล็นแจ็คแมน

0

ให้ไฟล์พร้อมข้อความลองใช้prและประมวลผลไวยากรณ์การแทนที่ดังนี้:

$ pr -mt <(grep -i "^[a-z]" file.txt) <(grep -i "^[0-9]" file.txt)
AAAA                    1234
BBBB                    5678
CCCC                    9012
DDDD                    3456
EEEE                    7890

คุณสามารถปรับความกว้างโดยหรือลบช่องว่างโดย-w9sed "s/ //g"

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.