วิธีพิมพ์ค่าในไฟล์ข้อความไปยังไฟล์คอลัมน์โดยใช้เชลล์สคริปต์


11

ฉันมี output.txt จากการรันเชลล์สคริปต์ดังนี้:

abc.txt
errorstatus1
Fri Nov 11 02:00:09 2016
def.txt
errorstatus2.txt
Sat Nov 12 03:00:09 2016

ไฟล์ข้อความมีหลายรายการทีละบรรทัดในลักษณะเดียวกัน ฉันต้องการพิมพ์ค่าเหล่านี้ลงในคอลัมน์: ชื่อไฟล์, สถานะและการประทับเวลาดังนี้:

Filename      Status        Timestamp
abc.txt     errorstatus1   Fri Nov 11 02:00:09 2016
def.txt     errorstatus2   Sat Nov 12 03:00:09 2016

4
รูปแบบตัวอย่างไม่ใช่ไฟล์ CSV มันเป็นไฟล์ความกว้างคอลัมน์คงที่ คุณอาจต้องการชี้แจงคำถามหรือให้ตัวอย่างที่ถูกต้อง
AlexP

ตัวอย่างของคุณไม่ใช่รูปแบบ CVS รูปแบบ CVS abc.txt,errorstatus1,Fri Nov 11 02:00:09 2016คือ ฉันแก้ไขคำถามของคุณเพื่อให้ตรงกับสิ่งที่พูดกับตัวอย่างที่คุณให้ไว้ อย่าลังเลที่จะย้อนกลับ แต่โปรดทราบว่าคุณต้องการชี้แจงอย่างชัดเจนว่าคุณต้องการอะไร - ค่าคอลัมน์หรือค่าที่คั่นด้วยเครื่องหมายจุลภาค
Sergiy Kolodyazhnyy

คำตอบ:


14

ด้วยpaste:

paste - - - <file.txt

สิ่งนี้จะเอาท์พุทเนื้อหาไฟล์ที่คั่นด้วยการขึ้นบรรทัดใหม่เป็นคอลัมน์และคอลัมน์ที่คั่นด้วยแท็บสามรายการต่อบรรทัด

การเพิ่มส่วนหัว:

echo Filename Status Timestamp; paste - - - <file.txt

ในการแบ่งคอลัมน์ผลลัพธ์ให้ใช้ความช่วยเหลือจากcolumn:

{ echo Filename Status Timestamp; paste - - - <file.txt ;} | column -t

ตัวอย่าง:

% cat file.txt
abc.txt
errorstatus1
Fri Nov 11 02:00:09 2016
def.txt
errorstatus2.txt
Sat Nov 12 03:00:09 2016

% { echo Filename Status Timestamp; paste - - - <file.txt ;} | column -t
Filename  Status            Timestamp
abc.txt   errorstatus1      Fri        Nov  11  02:00:09  2016
def.txt   errorstatus2.txt  Sat        Nov  12  03:00:09  2016

เย็น! ขอบคุณ !! แต่จะพิมพ์ค่าเหล่านี้ในรูปแบบ excel ได้อย่างไร ฉันต้องการส่วนหัวคอลัมน์ในแผ่นงาน Excel เป็นสถานะชื่อไฟล์และการประทับเวลาและค่าด้านล่างพวกเขา
34712 linux09

@ linux09 สร้าง CSV และนำเข้าด้วย Excel:echo Filename,Status,Timestamp; paste -d ',' - - - <file.txt
heemayl

ยอดเยี่ยม! ทำงานเหมือนจับใจ ขอบคุณมาก
linux09

6

คุณสามารถใช้ awk:

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

ผลลัพธ์อาจไม่สวยเท่าที่ควร:

$ awk 'NR % 3 {printf "%s ", $0; next} 1' input
abc.txt errorstatus1 Fri Nov 11 02:00:09 2016
def.txt errorstatus2.txt Sat Nov 12 03:00:09 2016

คุณสามารถใช้ %s\tแทนเอาต์พุตที่คั่นด้วยแท็บ

  • NR % 3เป็นศูนย์ (และเท็จ) สำหรับทุกบรรทัดที่สามดังนั้นบรรทัดอื่น ๆ จะถูกพิมพ์ด้วยช่องว่างหลังจากที่พวกเขาแทนการขึ้นบรรทัดใหม่ nextเพิ่งเริ่มต้นการทำซ้ำต่อไป
  • ทุกบรรทัดที่สามถูกพิมพ์ตาม - เป็นเพราะสุดท้าย1ด้วยบรรทัดใหม่หลังจากนั้นเนื่องจากมันไม่ตรงกับบล็อกแรก

5

นอกจากนี้ยังมีrs(BSD R E sยูทิลิตี้ Hape):

DESCRIPTION
     rs reads the standard input, interpreting each line as a row of blank-
     separated entries in an array, transforms the array according to the
     options, and writes it on the standard output.  With no arguments it
     transforms stream input into a columnar format convenient for terminal
     viewing.

โดยเฉพาะอย่างยิ่ง,

     -e      Consider each line of input as an array entry.

ดังนั้น

$ rs -e < file
abc.txt                   errorstatus1              Fri Nov 11 02:00:09 2016
def.txt                   errorstatus2.txt          Sat Nov 12 03:00:09 2016

หรือ (เพื่อเพิ่มส่วนหัว)

$ { printf '%s\n' Filename Status Timestamp ; cat file ; } | rs -e
Filename                  Status                    Timestamp
abc.txt                   errorstatus1              Fri Nov 11 02:00:09 2016
def.txt                   errorstatus2.txt          Sat Nov 12 03:00:09 2016

3

เพื่อความสมบูรณ์คุณสามารถทำได้ด้วยsed:

sed -e '1iFilename\tStatus\tTimestamp' -e 'N;N;y/\n/\t/' file.txt
  • 1iFilename\tStatus\tTimestamp แทรกบรรทัดส่วนหัวก่อนบรรทัด 1
  • N;N อ่านสองบรรทัดเพิ่มเติมในบัฟเฟอร์รูปแบบโดยให้บรรทัดที่คั่นด้วย newline ทั้งหมด 3 บรรทัด
  • y/\n/\t/ แทนที่บรรทัดใหม่ทั้งหมดด้วยแท็บในบัฟเฟอร์รูปแบบ

i, Nและyคำสั่ง sed มีเอกสารที่นี่


เยี่ยมมาก .. คุณสามารถแสดงความคิดเห็นสั้น ๆ เกี่ยวกับนิพจน์ที่คุณใช้ด้วยหรือไม่ ขอบคุณ!
Campa

ใช่เพื่อนที่สมบูรณ์แบบ
Campa

1

เป็นไปได้เสมอที่จะทำอาหารสำหรับการประมวลผลข้อความด้วย AWK หรือ Perl และแน่นอน Python ซึ่งเป็นคำตอบที่ให้

ในฐานะที่เป็นหนึ่งซับ:

python -c 'import sys;print "Filename\tStatus\tTimestamp"; lines=[l.strip() for l in sys.stdin];print "".join([l+"\n" if i%3 == 0 else l+"\t" for i,l in enumerate(lines,1) ])' < input.txt

เป็นสคริปต์หลายบรรทัด

import sys
print "Filename\tStatus\tTimestamp"
lines=[l.strip() for l in sys.stdin]
print "".join([l+"\n" if i%3 == 0 else l+"\t" for i,l in enumerate(lines,1) ])

แนวคิดพื้นฐานที่นี่คือให้อินพุตสคริปต์ผ่าน stdin (โดยใช้การเปลี่ยนเส้นทางของเชลล์<แม้ว่าสามารถใช้ไพพ์ได้เช่นกัน) สคริปต์ใช้แท็บเพื่อแยกฟิลด์แม้ว่าจะสามารถใช้ช่องว่างได้เช่นกันสำหรับเอาต์พุต "fine-tuned" เพิ่มเติม

เอาต์พุตตัวอย่างโดยใช้ตัวอย่างอินพุตที่จัดเตรียมโดย OP:

$ python -c 'import sys;print "Filename\tStatus\tTimestamp";                                   
> lines=[l.strip() for l in sys.stdin];
> print "".join([l+"\n" if i%3 == 0 else l+"\t" for i,l in enumerate(lines,1) ])' < input.txt
Filename    Status  Timestamp
abc.txt errorstatus1    Fri Nov 11 02:00:09 2016
def.txt errorstatus2    Sat Nov 12 03:00:09 2016
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.