हैलो मुझे एक साधारण समस्या है मुझे txt फ़ाइल में विशिष्ट पंक्तियों को खोजने की आवश्यकता है जिसमें उन्हें 'एलजी' शामिल करना है जो इस तरह दिखते हैं:

>NC_037638.1 Apis mellifera strain DH4 linkage group LG1, Amel_HAv3.1, whole genome shotgun sequence

तो मुझे इस मामले में संख्या NC_037638.1 को LG1 से बदलने की आवश्यकता है LG और नंबर हर लाइन में अलग होंगे

परिणाम इस तरह दिखना चाहिए:

>LG1, Apis mellifera strain DH4 linkage group LG1, Amel_HAv3.1, whole genome shotgun sequence

मुझे एक फ़ाइल में 3 मिलियन लाइनें पसंद हैं और मुझे केवल उन लोगों को खोजने की आवश्यकता है जिनके पास एलजी है और उसके बाद कुछ नंबर हैं जैसे उदाहरण LG1

तो मूल रूप से मुझे इससे प्राप्त करने की आवश्यकता है: यहां छवि विवरण दर्ज करें

इसके लिए: यहां छवि विवरण दर्ज करें

मैंने कुछ इस तरह लिखा:

#!/bin/bash
while IFS= read -r line; do
    if [[ $line =~ "LG" ]]; then
        echo $line | awk ' { t = $1; $1 = $8; print; } '  | sed -e 's/^/>/' >> nowy.txt
    else
        echo $line >> nowy.txt
    fi
done < kopia_pliku_docelowego

और यह काम करता है लेकिन इसकी अति धीमी स्क्रिप्ट को समाप्त होने में 3 मिनट लगते हैं

मैंने समाधान के बारे में सोचा और मुझे लगा कि मैं लाइन इंडेक्स के लिए grep कर सकता हूं और केवल उन पंक्तियों को बदल सकता हूं, फिर उसी इंडेक्स पर पुरानी लाइनों को स्वैप कर सकता हूं जैसे कि नया फिर से लिखा गया।

मुझे पता है कि सूचकांक कैसे खोजना है (grep -n) और मुझे पता है कि लाइन कैसे बदलनी है (एलजी के साथ स्वैपिंग नंबर के बारे में बात करना) लेकिन मुझे नहीं पता कि यह सब एक साथ कैसे रखा जाए।

थोड़ी सहायता वास्तव में प्रशंसनीय होगी

-2
antekkalafior 22 नवम्बर 2021, 17:47
आप कहीं न कहीं उन सभी पंक्तियों की खोज कर रहे हैं जिनमें स्ट्रिंग LG है, न कि केवल वे जो किसी संख्या का अनुसरण करती हैं। एक नंबर के साथ एलजी रखने के लिए एक लाइन का मिलान करने के लिए, [[ $line == *LG[0-9]* ]] होगा।
 – 
user1934428
22 नवम्बर 2021, 17:54
1
: यह प्रत्येक स्ट्रिंग NC_037638.1 को LG1 से बदल देगा, यहां तक ​​कि उन पंक्तियों में भी नहीं जिनमें कोई LG नहीं है।
 – 
user1934428
22 नवम्बर 2021, 17:55
@antekkalafior: पैटर्न से मेल खाने वाली प्रत्येक एकल पंक्ति के लिए, आप 2 चाइल्ड प्रोसेस (awk और sed) बना रहे हैं। मैं सब कुछ या तो बैश में या awk में ही करूंगा।
 – 
user1934428
22 नवम्बर 2021, 17:57
1
इसलिए मैंने कहा था कि आपको चाइल्ड प्रोसेस से बचना चाहिए.....
 – 
user1934428
22 नवम्बर 2021, 18:04
1
while read | awk आमतौर पर केवल awk की तुलना में कई गुना धीमी गति से चलेगी। while लूप का प्रयोग बंद करें; awk इनपुट को सीधे पढ़ने दें। इसमें अच्छा है।
 – 
William Pursell
22 नवम्बर 2021, 18:10

3 जवाब

सबसे बढ़िया उत्तर

मैं वास्तव में समस्या विवरण को नहीं समझता। ऐसा लगता है कि आप किसी भी पंक्ति में पहले कॉलम को 8वें कॉलम से बदलना चाहते हैं जिसमें LG है। अगर ऐसा है, तो बस करें:

awk '/LG/{ $1 = $8 }1' kopia_pliku_docelowego > nowy.txt

लेकिन शायद आप मैच को प्रतिबंधित करना चाहते हैं ताकि आप प्रतिस्थापन केवल तभी करें जब 'एलजी' 8वें कॉलम में दिखाई दे। आप इसके साथ ऐसा कर सकते हैं:

awk '$8 ~ /LG/{ $1 = $8 }1'

यदि आप चाहते हैं कि LG अंकों की एक स्ट्रिंग द्वारा पीछा किया जाए, तो इसका उपयोग करें:

awk '$8 ~ /LG[0-9]+/{ $1 = $8 }1'

यदि आपके पास ऐसी लाइनें हैं जिनमें 8वां कॉलम LGxxxAAA है (अंकों के बाद गैर स्ट्रिंग मान) और आप केवल पहले कॉलम को स्ट्रिंग के उस हिस्से से बदलना चाहते हैं जो LG[0-9+] से मेल खाता हो, तो आप इसका उपयोग कर सकते हैं:

awk 'match($8,/LG[0-9]+/){ $1 = substr($8,0,RLENGTH) }1'

awk निस्संदेह आपकी समस्या का समाधान कर सकता है, लेकिन आपको यह स्पष्ट करना होगा कि आप वास्तव में क्या मिलान करने का प्रयास कर रहे हैं। ऐसा लगता है कि आपका sed समाधान एक प्रमुख > सम्मिलित कर रहा है जो आपके विवरण के अनुसार आवश्यक नहीं लगता है। अधिक विशिष्टता की आवश्यकता है।

1
William Pursell 22 नवम्बर 2021, 18:27
यह वही है जो मैं ढूंढ रहा था। आपका बहुत बहुत धन्यवाद
 – 
antekkalafior
22 नवम्बर 2021, 18:29

आप इसे एक ही sed में कर सकते हैं:

sed -i.bak -E 's/^>NC_037638\.1(.* (LG[0-9]+))/>\2\1/' file

cat file

>LG1 Apis mellifera strain DH4 linkage group LG1, Amel_HAv3.1, whole genome shotgun sequence

स्पष्टीकरण:

  • ^>: मैच शुरू होने के बाद > का मिलान करें
  • NC_037638\.1: टेक्स्ट का मिलान करें NC_037638.1
  • (.* : Nn कैप्चर ग्रुप #1 से मेल खाता है और किसी भी टेक्स्ट को कैप्चर करता है और उसके बाद स्पेस देता है...
  • (LG[0-9]+)): LG का मिलान करें और उसके बाद कैप्चर ग्रुप #2 . में 1+ नंबर लगाएं
  • >\2\1: > के लिए रिप्लेसमेंट पार्ट के बाद LG सबस्ट्रिंग (जिसे हमने ग्रुप #2 में कैप्चर किया) उसके बाद कैप्चर ग्रुप #1 का बैक-रेफरेंस
0
Renaud Pacalet 22 नवम्बर 2021, 18:20
यह वह नहीं है जिसकी मुझे तलाश है। मैंने प्रश्न को फिर से लिखा ताकि इसे और अधिक समझा जा सके
 – 
antekkalafior
22 नवम्बर 2021, 18:16
दुर्भाग्य से वास्तविक पाठ के बजाय चित्र लगाने से इसे समझना बहुत मुश्किल हो जाता है। यदि आप छवियों को छोटे टेक्स्ट स्निपेट से बदलते हैं तो यह अधिक स्पष्ट होगा
 – 
anubhava
22 नवम्बर 2021, 18:22
It's not what i'm looking for कृपया इसे स्पष्ट करें क्योंकि यह उत्तर मेरे द्वारा टिप्पणियों में पूछे गए प्रश्न पर आधारित है और आपने उत्तर दिया thats correct
 – 
anubhava
22 नवम्बर 2021, 18:25

बस awk, शायद:

awk '{
  for(i=1;i<NF-1;i++)
    if($i=="linkage" && $(i+1)=="group")
      break
  if(i!=NF-1)
    $1=$(i+2)
  print
}' file.txt

हम लगातार दो शब्दों "linkage" और "group" की खोज करते हैं, बस अगर वे हमेशा पंक्तियों में एक ही स्थिति में नहीं होते हैं। मुझे संदेह है कि यह "एपिस मेलिफेरा" के कारण हो सकता है जो एक स्थान वाले एकल फ़ील्ड की तरह दिखता है। अगर हमें ये दो शब्द मिलते हैं तो हम पहले फ़ील्ड को "लिंकेज ग्रुप" के बाद वाले फ़ील्ड से बदल देते हैं।

यदि "लिंकेज समूह" का अनुसरण करने वाली फ़ील्ड और अधिक सीमित होनी चाहिए, उदा. होने के लिए LGnnn जहां nnn अंकों की कुछ स्ट्रिंग है, हम स्थिति को थोड़ा बदल सकते हैं:

awk '{
  for(i=1;i<NF-1;i++)
    if($i=="linkage" && $(i+1)=="group" && $(i+2) ~ /^LG[[:digit:]]+/)
      break;
  if(i!=NF-1)
    $1=$(i+2)
  print
}' file.txt
0
Renaud Pacalet 22 नवम्बर 2021, 18:49