सीड कमांड की श्रृंखला कमांड लाइन पर काम करती है, लेकिन स्क्रिप्ट में नहीं


9

मैं इस एसई डेटा क्वेरी के .csvआउटपुट के साथ काम कर रहा हूं जो इस तरह दिखता है (केवल 5022 प्रविष्टियों के साथ):

"{
  ""id"": 281952,
  ""title"": ""Flash 11.2 No Longer Supported by Google Play""
}"
"{
  ""id"": 281993,
  ""title"": ""Netbeans won't open in Ubuntu""
}"

(और इसमें ^M[संख्या] और "" शीर्षक "" के बीच की रेखा अंत है। मुझे इसे इस तरह देखना चाहिए:

281952,Flash 11.2 No Longer Supported by Google Play
281993,Netbeans won't open in Ubuntu

मैंने इसे एक निश्चित टेक्स्ट एडिटर में तय किया, जो काफी आसानी से बेकार हो जाएगा, लेकिन मैं एक स्क्रिप्ट बनाना चाहता था, ताकि मुझे हर बार फिर से क्वेरी रिफ्रेश होने पर ऐसा न करना पड़े, ताकि दूसरे इसका इस्तेमाल कर सकें। मैंने इस्तेमाल किया sed...

आदेशों की यह श्रृंखला पूरी तरह से काम करती है (हालाँकि यह अच्छी तरह से अक्षम हो सकती है; यह सिर्फ एक परीक्षण और त्रुटि समाधान है):

# Print the ^M and remove them, write to a new file:
cat -v QueryR* | sed 's/\^M//' > QueryNew
# remove all the other junk:
sed -i 's/{//' QueryNew
sed -i 's/}//' QueryNew
sed -i 's/""//g' QueryNew
sed -i 's/^"//' QueryNew
sed -i '/,/{N;/\n.*title:\s/{s/,\n.*title:\s/,\ /}}' QueryNew
sed -i 's/^\s\+//' QueryNew
sed -i '/^\s*$/d' QueryNew
sed -i 's/^id:\ //' QueryNew
sed -i 's/,\ /,/' QueryNew
sed -i 's/\\//g' QueryNew

तो, यह क्यों नहीं करता है? केवल ^Mऔर {}हटा दिया जाता है, और बाकी सब कुछ अभी भी है।

#!/bin/bash
cat -v QueryR* | sed 's/\^M//' > QueryNew
sed -i '{
       s/{//
       s/}//
       s/""//g
       s/^"//
       /,/{N;/\n.*title:\s/{s/,\n.*title:\s/,\ /}}
       s/^\s\+//
       /^\s*$/d
       s/^id:\ //
       s/,\ /,/
       s/\\//g
}' QueryNew

मुझे यकीन है कि मेरी गलती वास्तव में स्पष्ट है ...

जवाबों:


11

का उपयोग करते हुए cat -vशाब्दिक में सीआर पात्रों चालू करने के लिए ^Mदृश्यों मेरे लिए मौलिक रूप से बदसूरत लगता है - आप डॉस लाइन अंत, उपयोग को दूर करने की जरूरत है dos2unix, trया sed 's/\r$//'

आप sed का उपयोग कर पर जोर देते हैं, तो मैं सुझाव है कि आप बिट्स आप प्रिंट करते हैं बल्कि सभी यादृच्छिक बिट्स तुम नहीं हटाने का प्रयास करने से, चाहते हैं - उदाहरण के लिए

$ sed -rn -e 's/\"//g' -e 's/(.*): (.*)\r/\2/p' QueryR | paste -d '' - -
281952,Flash 11.2 No Longer Supported by Google Play
281993,Netbeans won't open in Ubuntu

आप मूल्य अनुक्रम के प्रत्येक छोर पर शून्य या अधिक उद्धरणों का मिलान करके फैंसी-वैल्यू को कुंजी-मूल्य निष्कर्षण में रोल कर सकते हैं

$ sed -rn 's/(.*): \"*([^"]*)\"*\r/\2/p' QueryR | paste -d '' - -
281952,Flash 11.2 No Longer Supported by Google Play
281993,Netbeans won't open in Ubuntu

आप वास्तव में कल्पना कर सकते हैं और अंत pasteमें sedपहले जोड़े की पंक्तियों में शामिल ,\r$होने और फिर कुंजी-मूल्य जोड़े को गुणा ( gऔर गैर-लालची) से जोड़कर अनुकरण कर सकते हैं

$ sed -rn '/,\r$/ {N; s/([^:]*): \"*([^:"]*)\"*\r\n?/\2/gp}' QueryR
281952,Flash 11.2 No Longer Supported by Google Play
281993,Netbeans won't open in Ubuntu

(व्यक्तिगत तौर पर मैं KISS दृष्टिकोण के पक्ष में है और पहले से इसका उपयोग करेंगे)।


FWIW, चूंकि आपका इनपुट JSON से अधिक उद्धृत किया गया है, इसलिए मैं एक उचित JSON पार्सर जैसे स्थापित करने का सुझाव दूंगा jq

sudo apt-get install jq

आप तब कुछ ऐसा कर सकते हैं

$ sed -e 's/["]["]/"/g' -e 's/"{/{/' -e 's/}"/}/' QueryR | jq '.id, .title' | paste -d, - -
281952,"Flash 11.2 No Longer Supported by Google Play"
281993,"Netbeans won't open in Ubuntu"

जो शानदार उद्धरणों को हटाता है और फिर jqब्याज के क्षेत्रों को निकालने के लिए उपयोग करता है - ध्यान दें कि jqडॉस-स्टाइल लाइन एंडिंग्स को संभालने के लिए लगता है, इसलिए उन्हें हटाने के लिए विशेष कदम उठाने की आवश्यकता नहीं है।

jq '.[]'सभी विशेषता-मूल्य जोड़े को डंप करने के लिए बदलें ।

प्रेरणा और बुनियादी jqवाक्यविन्यास के लिए श्रेय grep -o के साथ ओवरलाइनिंग से लिया गया है


1
उह, हाँ, मैं क्यों भूल गया \rjqपहली पंक्ति जहां शीर्षक क्षेत्र में एक बृहदान्त्र (पहली पंक्ति) थी, पर टूट गया। मुझे अब भी यकीन नहीं है कि sedमुझसे नफरत क्यों की जाती है, लेकिन मैंने कुछ उद्धरण और \rइस पंक्ति को मार दिया है /,\r*/{N;/\n.*title.*:\s/{s/,\r*\n.*title.*:\s/,\ /}}और अंत में यह इस तरह से काम करता है । बहुत बहुत धन्यवाद ^ _ ^
Zanna

1
यह बेहतर है (लेकिन मैं ऐसा कोई उद्धरण नहीं चाहता हूं sed -rn -e 's/\"\"//g' -e 's/^(.*): (.*)\r$/\2/p' QueryR* | paste -d '' - - और जादू की तरह किया हो)
Zanna

5

मैंने इसे स्टीलड्राइवर और आगे की टिंकरिंग के लिए धन्यवाद दिया। अपरिष्कृत लेकिन काम करता है।

sed  '{
       s/"{//
       s/}"//
       s/^"//
       /,\r/{N;/\n.*title.*:\s/{s/,\r\n.*title.*:\s/,/}}
       s/""//g
       s/^\s\+//
       /^\s*$/d
       s/^id:\ //
       s/\\//g
}' QueryR* | tee "$1"

अनुवाद:
s/"{//निकालें "{
s/}"//निकालें }"
s/^"//निकालें "लाइन की शुरुआत से
/,\r/{N;/\n.*title.*:\s/{s/,\r\n.*title.*:\s/,\ /}}मैच ,\rएक पंक्ति में और [whatever]title[whatever]:अगली पंक्ति पर, सभी की जगह उस के साथ ,
s/""//gनिकालें सभी शेष डबल डबल कोट्स
s/^\s\+//लाइनों की शुरुआत से निकालें खाली स्थान के
/^\s*$/dनिकालें खाली लाइनों
s/^id:\ //निकालें id:और अंतरिक्ष के बाद यह
s/\\//gके लिए (भागने वर्ण बैकस्लैश निकालें "कुछ शीर्षक क्षेत्रों में जोड़ा जाता है)
tee "$1"स्क्रिप्ट चलाते समय एक संगठन निर्दिष्ट करें, उदाहरण के लिए./queryclean newquery.csv


4

हालांकि सवाल यह है कि sed, अजगर के साथ sed के मुद्दों पर काम कर सकता है:

from __future__ import print_function
import sys

with open(sys.argv[1]) as f:
     for line in f:
         if '""id""' in line:
            print(line.strip().split(':')[1],end="")
         if '""title""' in line:
            title = " ".join(line.strip().split(':')[1:])
            print(title.replace('""'," "))

यह कोड python2 और python3 दोनों के अनुरूप है, इसलिए या तो काम करेगा

नमूना रन:

bash-4.3$ cat questions.txt 
"{
  ""id"": 281952,
  ""title"": ""Flash 11.2 No Longer Supported by Google Play""
}"
"{
  ""id"": 281993,
  ""title"": ""Netbeans won't open in Ubuntu""
}"
bash-4.3$ python3 parse_questions.py questions.txt 
 281952,  Flash 11.2 No Longer Supported by Google Play 
 281993,  Netbeans won't open in Ubuntu 

4

तीन और दृष्टिकोण:

  1. awk

    $ awk -F'": ' '/\"id\"/{id=$NF;} 
                  /\"title\"/{
                    t=$NF; 
                    sub(/^""/,"",t); 
                    sub(/""$/,"",t); 
                    print id,t
                  }' OFS="" file 
    281952,Flash 11.2 No Longer Supported by Google Play
    281993,Netbeans won't open in Ubuntu
  2. पर्ल

    $ perl -lne '$id=$1 if /id"":\s*(\d+)/; 
                 if(/title"":\s*""(.*)""/){print "$id,$1"}' file 
    281952,Flash 11.2 No Longer Supported by Google Play
    281993,Netbeans won't open in Ubuntu
  3. जीएनयू जीआरई पेरेल संगत रिजेक्स और सरल पर्ल:

    $ grep -oP '(id"":\s*\K.*)|(title"":\s*""\K.*(?=""))' file | 
        perl -pe 'chomp if $.%2'
    281952,Flash 11.2 No Longer Supported by Google Play
    281993,Netbeans won't open in Ubuntu

4

यह वास्तव में आपके प्रश्न का उत्तर नहीं दे रहा है या आपके मुद्दे को हल नहीं कर रहा है, लेकिन उन अवांछित वर्णों से छुटकारा पाने के लिए जिन्हें आप tr का उपयोग कर सकते हैं :

cat QueryR | tr -d '}{:"' 

और आपको मिलेगा:

यहां छवि विवरण दर्ज करें


धन्यवाद, मुझे सीखने की आवश्यकता है tr:)
Zanna

यह sed या awk जितना शक्तिशाली नहीं है लेकिन यह उस तरह की चीजों के लिए बहुत सीधा है। चीयर्स :)
kcdtv

1

यह रूबी में लिखी गई एक और स्क्रिप्ट है। यह शीर्षक में अल्पविराम को बनाए रखेगा, जिसे स्तंभों को तोड़ने के बिना किसी भी स्प्रेडशीट कार्यक्रम में आसानी से आयात किया जा सकता है।

csvfile = File.open('query-fixed.csv', 'w')

File.open('QueryResults2.csv') do |f|
    content = f.read
    content.gsub!(/\r\n?/, "\n")
    content.each_line do |line|
        id, title = '', ''
        if line.match('\"id\"')
            id = line.split(':')[1].strip[0..-2]
            csvfile.write(id + ',')
        end
        if line.match('\"title\"')
            title = line.partition(':')[2].scan(/"(.*)"/)[0][0]
            csvfile.write(title + "\n")
        end
    end
end

प्रोग्राम चलाने के बाद उत्पादित आउटपुट इन जैसा दिखेगा

281952,"Flash 11.2 No Longer Supported by Google Play"
281993,"Netbeans won't open in Ubuntu"

यह बहुत अच्छा है :)
Zanna

:उनके बारे में शीर्षक के साथ कैसे ?
Sain16ошƒаӽ

@ SANƒошƒаӽ उफ़! सूचक के लिए धन्यवाद। अब तय!
अनवर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.