तलछट के साथ पाठ हेरफेर


12

वर्तमान में, मेरे पास इस तरह की सामग्री के साथ कई पाठ फ़ाइलें हैं (कई पंक्तियों के साथ):

565 0 10 12 23 18 17 25
564 1 7 12 13 16 18 40 29 15

मैं निम्नलिखित प्रारूप के लिए प्रत्येक पंक्ति को बदलना चाहता हूं:

0 565:10:1 565:12:1 565:23:1 565:18:1 565:17:1 565:25:1
1 564:7:1 564:12:1 564:13:1 564:16:1 564:18:1 564:40:1 564:29:1 564:15:1

क्या सीड का उपयोग करके उपरोक्त कोई भी तरीका है? या मुझे पायथन का सहारा लेने की आवश्यकता है?

जवाबों:


22

आप इसे सेड के साथ कर सकते हैं, हाँ, लेकिन अन्य टूल सरल हैं। उदाहरण के लिए:

$ awk '{
        printf "%s ", $2; 
        for(i=3;i<=NF;i++){
            printf "%s:%s:1 ",$1,$(i) 
        }
        print ""
       }' file 
0 565:10:1 565:12:1 565:23:1 565:18:1 565:17:1 565:25:1 
1 564:7:1 564:12:1 564:13:1 564:16:1 564:18:1 564:40:1 564:29:1 564:15:1 

व्याख्या

awk के रूप में प्रत्येक क्षेत्रों की बचत, खाली स्थान के (डिफ़ॉल्ट रूप से) पर इनपुट की प्रत्येक पंक्ति बंट जाएगा $1, $2, $N। इसलिए:

  • printf "%s ", $2; 2 क्षेत्र और एक अनुगामी स्थान प्रिंट करेगा।
  • for(i=3;i<=NF;i++){ printf "%s:%s:1 ",$1,$(i) }: फ़ील्ड 3 से अंतिम फ़ील्ड (फ़ील्ड NFकी संख्या) पर पुनरावृति करेगा और उनमें से प्रत्येक के लिए यह 1 फ़ील्ड :, फिर वर्तमान फ़ील्ड और ए :1
  • print "" : यह सिर्फ एक अंतिम newline प्रिंट करता है।

या पर्ल:

$ perl -ane 'print "$F[1] "; print "$F[0]:$_:1 " for @F[2..$#F]; print "\n"' file 
0 565:10:1 565:12:1 565:23:1 565:18:1 565:17:1 565:25:1 
1 564:7:1 564:12:1 564:13:1 564:16:1 564:18:1 564:40:1 564:29:1 564:15:1 

व्याख्या

-aबनाता है perlकी तरह व्यवहार awkऔर रिक्त स्थान को पर अपने इनपुट अलग हो गए। यहां, फ़ील्ड को सरणी में संग्रहीत किया जाता है @F, जिसका अर्थ है कि 1 क्षेत्र होगा $F[0], दूसरा $F[1]आदि।

  • print "$F[1] " : दूसरा फ़ील्ड प्रिंट करें।
  • print "$F[0]:$_:1 " for @F[2..$#F];: फ़ील्ड 3 से अंतिम फ़ील्ड पर है ( $#Fसरणी में तत्वों की संख्या है @F, इसलिए @F[2..$#F]सरणी के अंत तक 3 तत्व से शुरू होने वाला एक सरणी टुकड़ा लेता है) और 1 फ़ील्ड को प्रिंट करें, ए :, और फिर वर्तमान फ़ील्ड और एक :1
  • print "\n" : यह सिर्फ एक अंतिम newline प्रिंट करता है।

12

यहां है भयंकर sed मार्ग!

$ sed -r 's/^([0-9]+) ([0-9]+) ([0-9]+)/\2 \1:\3:1/; :a s/([0-9]+)(:[0-9]+:1) ([0-9]+)( |$)/\1\2 \1:\3:1 /; t a; s/ $//' file
0 565:10:1 565:12:1 565:23:1 565:18:1 565:17:1 565:25:1 
1 564:7:1 564:12:1 564:13:1 564:16:1 564:18:1 564:40:1 564:29:1 564:15:1

अधिक आसानी से:

sed -r '
s/^([0-9]+) ([0-9]+) ([0-9]+)/\2 \1:\3:1/
:a 
s/([0-9]+)(:[0-9]+:1) ([0-9]+)( |$)/\1\2 \1:\3:1 /
t a
s/ $//'

टिप्पणियाँ

  • -r ERE का उपयोग करें
  • s/old/new/के oldसाथ बदलेंnew
  • ^([0-9]+) लाइन के शुरू में कुछ नंबर सेव करें
  • \1 पहले सहेजे गए पैटर्न के लिए पश्चगामी
  • :a स्क्रिप्ट के इस भाग को लेबल करें a
  • ( |$) या तो एक स्थान या पंक्ति का अंत
  • t परीक्षण करें कि क्या अंतिम प्रतिस्थापन सफल था - यदि यह था, तो अगली कमांड करें
  • aलेबल ढूंढें :aऔर इसे फिर से करें
  • s/ $// पीछे की जगह को हटा दें

इसलिए पहले भाग में संरचना को जोड़ने के बाद, हम बार-बार संरचना का अंतिम उदाहरण ढूंढते हैं और इसे अगले नंबर पर लागू करते हैं ...

लेकिन मैं मानता हूं कि अन्य उपकरण इसे आसान बनाते हैं ...


मुझे आपके
सेड

: D यह मुझे थोड़ी देर लगी @Ravexina - I reckon muru एक क्लीनर बना सकता है
Zanna

5

Awk के साथ:

awk '{printf "%s ",$2; for (i=3; i<=NF; i++) printf $1":"$i":1 "; printf "\n"}' file

या बैश के साथ:

while read -r -a a; do                  # read line to array a
  printf "%s " ${a[1]}                  # print column #1
  for ((i=2;i<${#a[@]};i++)); do        # loop from column #2 to number of columns
    printf "%s " "${a[0]}:${a[$i]}:1"   # print content/values
  done
  echo                                  # print line break
done < file                             # read file from stdin

आउटपुट:

0 565: 10: 1 565: 12: 1 565: 23: 1 565: 18: 1 565: 17: 1 565: 25: 1 
1 564: 7: 1 564: 12: 1 564: 13: 1 564: 16: 1 564: 18: 1 564: 40: 1 564: 29: 1 564: 15: 1 

5

ठीक है, आप इसे सेड में कर सकते हैं, लेकिन अजगर भी काम करता है।

$ ./reformatfile.py  input.txt                                                                        
0 565:10:1 565:12:1 565:23:1 565:18:1 565:17:1 565:25:1
1 564:7:1 564:12:1 564:13:1 564:16:1 564:18:1 564:40:1 564:29:1 564:15:1

इस प्रकार reformatfile.pyहैं:

#!/usr/bin/env python3
import sys

with open(sys.argv[1]) as fd:
    for line in fd:
        words = line.strip().split()
        pref = words[0]
        print(words[1],end=" ")
        new_words = [ ":".join([pref,i,"1"]) for i in words[2:] ]
        print(" ".join(new_words))

यह कैसे काम करता है? वास्तव में कुछ खास नहीं चल रहा है। हम पढ़ने के लिए फ़ाइल के रूप में पहला कमांड-लाइन तर्क खोलते हैं और प्रत्येक पंक्ति को "शब्दों" या व्यक्तिगत मदों में तोड़ते हुए आगे बढ़ते हैं। पहले शब्द prefपरिवर्तनशील हो जाते हैं, और हम दूसरी जगह (शब्द [1]) आइटम को अंतरिक्ष से समाप्त करते हुए प्रिंट करते हैं। अगला हम सूची बोध के माध्यम से "शब्दों" के नए सेट का निर्माण करते हैं और .join()प्रीफ़, प्रत्येक शब्द और स्ट्रिंग की एक अस्थायी सूची पर कार्य करते हैं "1"। अंतिम चरण उन लोगों को प्रिंट करना है


4

के साथ awk:

awk '{printf("%s ", $2); for(i=3; i<NF; i++) printf("%s:%s:1 ", $1, $i);\
          printf("%s:%s:1\n", $1, $NF)}' file.txt

यह वांछित प्रारूप में अंतरिक्ष से अलग किए गए फ़ील्ड को प्रारूपित करने के बारे में है:

  • printf("%s ", $2) दूसरे क्षेत्र को एक अनुगामी स्थान के साथ प्रिंट करता है

  • for(i=3; i<NF; i++) printf("%s:%s:1 ", $1, $i) 3 से दूसरे अंतिम फ़ील्ड पर पुनरावृत्त करता है और वांछित प्रारूप में फ़ील्ड प्रिंट करता है (पहले फ़ील्ड, फिर एक कोलन, फिर वर्तमान फ़ील्ड, फिर कॉलन, अंत में 1) एक अनुगामी स्थान के साथ

  • printf("%s:%s:1\n", $1, $NF) नई फ़ील्ड के साथ अंतिम फ़ील्ड प्रिंट करता है

उदाहरण:

% cat file.txt
565 0 10 12 23 18 17 25
564 1 7 12 13 16 18 40 29 15

% awk '{printf("%s ", $2); for(i=3; i<NF; i++) printf("%s:%s:1 ", $1, $i); printf("%s:%s:1\n", $1, $NF)}' file.txt
0 565:10:1 565:12:1 565:23:1 565:18:1 565:17:1 565:25:1
1 564:7:1 564:12:1 564:13:1 564:16:1 564:18:1 564:40:1 564:29:1 564:15:1
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.