2015-08-21 2 views
7

क्या प्रत्येक लाइन के अद्वितीय पात्र निकालने का कोई तरीका है?इनपुट की प्रति पंक्ति अद्वितीय वर्ण कैसे प्राप्त कर सकता हूं?

मैं मैं

sort -u file 

का उपयोग कर रहा प्रत्येक पंक्ति का विशेष अक्षर (प्रत्येक पंक्ति के लिए sort -u की तरह कुछ) निर्धारित करने के लिए चाहते हैं एक फ़ाइल के अद्वितीय लाइनों पा सकते हैं पता है।

स्पष्ट करने के लिए: दिए गए इस इनपुट:

111223234213 
111111111111 
123123123213 
121212122212 

मैं इस उत्पादन प्राप्त करना चाहते हैं:

1234 
1 
123 
12 

उत्तर

5

sed का उपयोग कर

sed ':;s/\(.\)\(.*\)\1/\1\2/;t' file 

मूल रूप से उसके द्वारा एक चरित्र को पकड़ने और अगर यह लाइन पर और कहीं भी दिखाई देता है है। यह इन दोनों के बीच के सभी पात्रों को भी कैप्चर करता है। फिर यह उन सभी जगहों को प्रतिस्थापित करता है जिनमें दूसरे मौके के साथ पहली बार मौका था और फिर बीच में क्या था।

t परीक्षण किया गया है और पिछले आदेश सफल होने पर : लेबल पर कूदता है। फिर यह तब तक दोहराता है जब तक s/// कमांड विफल रहता है जिसका मतलब केवल अद्वितीय वर्ण ही रहते हैं।

; बस आदेशों को अलग करता है।

1234 
1 
123 
12 

आदेश भी जारी रखता है।

+0

यह छोटा है! ':;' और 't' क्या हैं? – user1436187

+0

@ user1436187 जोड़ा गया स्पष्टीकरण – 123

+1

और मैं इसे उत्तर के रूप में स्वीकार करता हूं! – user1436187

3

यह मूल आदेश में चीजों को नहीं मिलता है, लेकिन इस awk एक लाइनर काम करने के लिए लगता है:

awk '{for(i=1;i<=length($0);i++){a[substr($0,i,1)]=1} for(i in a){printf("%s",i)} print "";delete a}' input.txt 

स्प्लिट के अलावा आसानी से पढ़ने के लिए, यह हो सकता है स्टैंड-अलोन इस तरह:

#!/usr/bin/awk -f 

{ 
    # Step through the line, assigning each character as a key. 
    # Repeated keys overwrite each other. 
    for(i=1;i<=length($0);i++) { 
    a[substr($0,i,1)]=1; 
    } 

    # Print items in the array. 
    for(i in a) { 
    printf("%s",i); 
    } 

    # Print a newline after we've gone through our items. 
    print ""; 

    # Get ready for the next line. 
    delete a; 
} 
बेशक

, इसी अवधारणा बहुत आसानी से शुद्ध बैश में रूप में अच्छी तरह से लागू किया जा सकता है:

#!/usr/bin/env bash 

while read s; do 
    declare -A a 
    while [ -n "$s" ]; do 
    a[${s:0:1}]=1 
    s=${s:1} 
    done 
    printf "%s" "${!a[@]}" 
    echo "" 
    unset a 
done < input.txt 

ध्यान दें कि यह साहचर्य सरणी की वजह से पार्टी 4 पर निर्भर करता है,। और यह एक चीजें मूल क्रम में प्राप्त करता है, क्योंकि बैश अजीब की तुलना में सरणी कुंजियों को रखने का बेहतर काम करता है।

और मुझे लगता है कि आपको जोस से sed का उपयोग करके समाधान मिला है, हालांकि इसमें अतिरिक्त पाइप-फिटिंग शामिल है। :)

आपके द्वारा उल्लिखित अंतिम टूल grep था। मुझे पूरा यकीन है कि आप पारंपरिक grep में ऐसा नहीं कर सकते हैं, लेकिन शायद कुछ बहादुर आत्मा -o और लुकराउंड का उपयोग कर एक पर्ल-रेगेक्सपी संस्करण (यानी grep -P) बनाने में सक्षम हो सकती है। यद्यपि वे अभी मुझमें से अधिक कॉफी की आवश्यकता होगी।

1

यह awk काम करना चाहिए:

awk -F '' '{delete a; for(i=1; i<=NF; i++) a[$i]; for (j in a) printf "%s", j; print ""}' file 
1234 
1 
123 
12 

यहाँ: गैर के लिए:

-F '' हमें $1 में एकल वर्ण देने, $2 आदि

नोट चार से रिकॉर्ड चार टूट जाएगा -gnu awk उपयोग:

awk 'BEGIN{FS=""} {delete a; for(i=1; i<=NF; i++) a[$i]; 
     for (j in a) printf "%s", j; print ""}' file 
3

एक अन्य समाधान,

while read line; do 
    grep -o . <<< $line | sort -u | paste -s -d '\0' -; 
done < file 

grep -o . परिवर्तित 'पंक्ति लाइन' 'कॉलम लाइन'
sort -u प्रकार पत्र और दूर करने के लिए repetead पत्र
'पंक्ति लाइन'
- के रूप में paste -s -d '\0' - परिवर्तित 'कॉलम लाइन' मानक इनपुट का उपयोग करने के लिए इसे बताने के लिए पेस्ट करने के लिए एक फ़ाइल नाम तर्क।

+0

अभिनव समाधान! संदर्भ के लिए, आपकी पाइप में पहली sed स्क्रिप्ट को '/ s/./&/g''' तक छोटा किया जा सकता है। और 'सॉर्ट | uniq' आमतौर पर 'sort -u' के साथ प्रतिस्थापित किया जा सकता है। इसके अलावा, क्या होगा यदि रेखाओं में से एक को रेखा पर छंटनी की जा रही है वास्तव में एक जगह है? – ghoti

+0

@ghoti किया, सही किया ..... बहुत बहुत धन्यवाद –

+0

आपका बहुत स्वागत है। ओह, और अपने sed स्क्रिप्ट के अंदर '\ n' से सावधान रहें। जो आपने अभी प्राप्त किया है वह अब जीएनयू sed के साथ काम करता है, लेकिन फ्रीबीएसडी, ओएसएक्स, सोलारिस इत्यादि में मौजूद sed के साथ नहीं। यदि आप ऐसी चीजें लिखते हैं जो पोर्टेबल नहीं हैं, तो तथ्य यह ध्यान रखना सबसे अच्छा है, या विकल्पों के साथ अनुभावा उसका GAWK समाधान। – ghoti

2

एक तरह से का उपयोग कर:

perl -F -lane 'print do { my %seen; grep { !$seen{$_}++ } @F }' file 

परिणाम:

1234 
1 
123 
12 
+0

सीखने के लिए स्टैक ओवरव्लो का उपयोग करना पसंद है मैं हमेशा perl द्वारा चिंतित हूं, लेकिन यह शायद ही कभी मुझे समझ में आता है। क्या आप समझा सकते हैं कि यह कैसे काम करता है? – ghoti

1

यह आपके लिए (जीएनयू sed) काम कर सकते हैं:

sed 's/\B/\n/g;s/.*/echo "&"|sort -u/e;s/\n//g' file 

स्प्लिट लाइनों की एक श्रृंखला में प्रत्येक पंक्ति । अद्वितीय उन पंक्तियों को क्रमबद्ध करें। परिणाम को एक पंक्ति में वापस मिलाएं।

+0

बिल्कुल सही! क्या आप कृपया इस भाग की व्याख्या करें/.*/ echo "&" '। – user1436187

+0

@ user1436187 'e' कमांड के लिए [यहां] (http://www.gnu.org/software/sed/manual/sed.html#Extended-Commands) देखें। यह वर्तमान स्थान में पैटर्न स्पेस का मूल्यांकन करने की अनुमति देता है और परिणाम पैटर्न स्थान में वापस रखा जाता है। – potong

0

अद्वितीय और दूसरों के लिए क्रमबद्ध विकल्प, एसईडी और GNU उपकरण का उपयोग कर:

sed 's/\(.\)/\1\n/g' file | sort | uniq 

जो प्रत्येक पंक्ति में एक चरित्र पैदा करता है; आप एक पंक्ति में उन चाहते हैं, बस करो:

sed 's/\(.\)/\1\n/g' file | sort | uniq | sed ':a;N;$!ba;s/\n//g;' 

इस बल्कि उपस्थिति के आदेश से, क्रमबद्ध क्रम में वर्ण दिखाने का लाभ दिया है।

संबंधित मुद्दे