उद्धृत प्रविष्टियों के साथ एक अल्पविराम से अलग सूची में अलग-अलग रेखाओं को बदलना


15

मेरे पास निम्न डेटा (एक Rmarkdown फ़ाइल से आर संकुल की सूची है), जिसे मैं एक सूची में बदलना चाहता हूँ जिसे मैं आर करने के लिए पास कर सकता हूँ:

d3heatmap
data.table
ggplot2
htmltools
htmlwidgets
metricsgraphics
networkD3
plotly
reshape2
scales
stringr

मैं सूची को प्रपत्र की सूची में बदलना चाहता हूं:

'd3heatmap', 'data.table', 'ggplot2', 'htmltools', 'htmlwidgets', 'metricsgraphics', 'networkD3', 'plotly', 'reshape2', 'scales', 'stringr'

वर्तमान में मेरे पास एक बैश पाइपलाइन है जो कच्ची फ़ाइल से ऊपर की सूची में जाती है:

grep 'library(' Presentation.Rmd \
| grep -v '#' \
| cut -f2 -d\( \
| tr -d ')'  \
| sort | uniq

मैं नई पंक्तियों को अल्पविराम से अलग की गई सूची में बदलने के लिए एक कदम जोड़ना चाहता हूं। मैंने जोड़ने की कोशिश की है tr '\n' '","', जो विफल रहता है। मैंने निम्नलिखित स्टैक ओवरफ्लो उत्तरों के कई प्रयास किए हैं, जो विफल भी होते हैं:

यह library(stringr)))phics)परिणाम के रूप में पैदा करता है ।

यह ,%परिणाम के रूप में पैदा करता है ।

यह उत्तर ( -iहटाए गए ध्वज के साथ ), इनपुट के समान आउटपुट का उत्पादन करता है।


क्या सीमांकक के लिए सीमांकक की आवश्यकता है, या अल्पविराम केवल स्वीकार्य है?
स्टीलड्राइवर

या तो ठीक है, लेकिन मैं या तो स्ट्रिंग आसपास के एक उद्धरण चरित्र की आवश्यकता है, 'या "
fbt


क्या मैं पहली बार नोटिस कर रहा हूं कि इनपुट डेटा और इसे प्रोसेस करने की स्क्रिप्ट पूरी तरह से असंगत है। कोई आउटपुट नहीं होगा।
ctrl-alt-delor-

मेरे द्वारा सूचीबद्ध स्क्रिप्ट है कि मैं इनपुट डेटा कैसे उत्पन्न करता हूं। किसी ने मांगा। वास्तविक इनपुट डेटा कुछ इस तरह दिखेगा इस । ध्यान दें कि गितुब नई लाइनों को हटाने के लिए स्वरूपण को बदलता है।
fbt

जवाबों:


19

आप sed के साथ उद्धरण जोड़ सकते हैं और फिर पेस्ट के साथ लाइनों को मर्ज कर सकते हैं , जैसे:

sed 's/^\|$/"/g'|paste -sd, -

यदि आप एक जीएनयू कोर्यूटिल्स आधारित प्रणाली (यानी लिनक्स) चला रहे हैं, तो आप अनुगामी को छोड़ सकते हैं '-'

यदि आपके पास इनपुट डेटा में डॉस-स्टाइल लाइन एंडिंग्स हैं (जैसा कि @ एफके ने सुझाव दिया है), तो आप कमांड को निम्नानुसार संशोधित कर सकते हैं:

sed 's/\r//;s/^\|$/"/g'|paste -sd, -

1
MacOS (और शायद अन्य) पर, आपको यह दर्शाने के लिए डैश को शामिल करना होगा कि इनपुट फ़ाइल के बजाय sed 's/^\|$/"/g'|paste -sd, -
स्टडिन से है

सच है, पेस्ट का "कोर्यूटिल्स" संस्करण दोनों रूपों को स्वीकार करेगा, लेकिन "-" अधिक पोसिक्स है। धन्यवाद !
जेपेलिन

2
या सिर्फ sedअकेले के साथ :sed 's/.*/"&"/;:l;N;s/\n\(.*\)$/, "\1"/;tl'
डिजिटल ट्रामा

1
@fbt मैंने अपने उत्तर के अंत में जो नोट जोड़ा है वह यहाँ भी लागू होता है।
phk

1
@DigitalTrauma - वास्तव में एक अच्छा विचार नहीं है; यह बहुत धीमा होगा (बड़ी फ़ाइलों के साथ लटका भी जा सकता है) - Q पर मेरी टिप्पणी में लिंक किए गए QI के उत्तर यहां देखें; ठंडी चीज pasteअकेले उपयोग करना है;)
don_crissti

8
का उपयोग कर awk:
awk 'BEGIN { ORS="" } { print p"'"'"'"$0"'"'"'"; p=", " } END { print "\n" }' /path/to/list
कम खोल से बचने और इसलिए अधिक पठनीय के साथ वैकल्पिक:
awk 'BEGIN { ORS="" } { print p"\047"$0"\047"; p=", " } END { print "\n" }' /path/to/list
आउटपुट:
'd3heatmap', 'data.table', 'ggplot2', 'htmltools', 'htmlwidgets', 'metricsgraphics', 'networkD3', 'plotly', 'reshape2', 'scales', 'stringr'
स्पष्टीकरण:

awkस्क्रिप्ट ही सब एस्केपिंग के बिना है BEGIN { ORS="" } { print p"'"$0"'"; p=", " } END { print "\n" }। पहली प्रविष्टि को प्रिंट करने के बाद चर pसेट किया जाता है (इससे पहले कि यह एक खाली स्ट्रिंग की तरह है)। इस चर के साथ pहर प्रविष्टि (या awk-स्पेक: रिकॉर्ड ) उपसर्ग है और इसके अलावा इसके चारों ओर एकल उद्धरण के साथ मुद्रित किया गया है। awkउत्पादन रिकॉर्ड विभाजक चर ORSकी जरूरत नहीं है (के बाद से उपसर्ग यह तुम्हारे लिए क्या कर रहा है) तो यह वह स्थान खाली होने के लिए सेट कर दिया जाता BEGINआईएनजी। ओह और हम अपनी फाइल को ENDएक नई पंक्ति के साथ ले सकते हैं (जैसे कि यह आगे के टेक्स्ट-प्रोसेसिंग टूल के साथ काम करता है); क्या इसके साथ भाग की आवश्यकता नहीं होनी चाहिए ENDऔर इसके बाद (एकल उद्धरण के अंदर) सब कुछ हटाया जा सकता है।

ध्यान दें

यदि आपके पास विंडोज / डॉस-स्टाइल लाइन एंडिंग्स ( \r\n) हैं, तो आपको उन्हें \nपहले UNIX स्टाइल ( ) में बदलना होगा । ऐसा करने के लिए आप tr -d '\015'अपनी पाइपलाइन की शुरुआत में रख सकते हैं :

tr -d '\015' < /path/to/input.list | awk […] > /path/to/output

(मान लें कि \rआपकी फ़ाइल में आपके लिए कोई उपयोग नहीं है । यहाँ बहुत सुरक्षित धारणा है।)

वैकल्पिक रूप से, dos2unix /path/to/input.listफ़ाइल को इन-प्लेस करने के लिए बस एक बार चलाएं ।


जब मैं यह कमांड चलाता हूं, तो मुझे ', 'stringr23aphicsआउटपुट के रूप में मिलता है ।
fbt

@fbt मेरा नवीनतम नोट देखें।
phk

2
print p"'"'"'"$0"'"'"'"; p=", "-होली उद्धरण, बैटमैन!
वचर्जिन

मैं जानता हूँ कि, right‽ :) मैं उल्लेख है कि कई गोले में प्रिंट के बारे में सोचा p"'\''"$0"'\''";होगा भी काम किया है (यह POSIXy नहीं है, हालांकि), या वैकल्पिक रूप का उपयोग कर bashके सी के हवाले से तार ( $'') यहां तक कि बस print p"\'"$0"\'";(अन्य बैकस्लैश हालांकि दोहरीकरण के लिए आवश्यक हो सकता है), लेकिन वहाँ पहले से ही अन्य विधि का उपयोग कर awkबच जाता है।
phk

वाह, मुझे विश्वास नहीं हो रहा है कि तुम समझ गए हो। धन्यवाद।
fbt

6

जैसा कि @ don_crissti के लिंक किए गए उत्तर से पता चलता है, पेस्ट ऑप्शन अविश्वसनीय रूप से तेज़ सीमा पर है - लाइनक्स कर्नेल की पाइपिंग मेरे द्वारा विश्वास किए जाने की तुलना में अधिक कुशल है अगर मैंने अभी-अभी इसकी कोशिश नहीं की थी। उल्लेखनीय रूप से, यदि आप एक अल्पविराम से खुश हो सकते हैं एक अल्पविराम के बजाय अपनी सूची की वस्तुओं को अलग करके, एक जगह, एक पाइपलाइन

(paste -d\' /dev/null - /dev/null | paste -sd, -) <input

एक उचित flexकार्यक्रम से भी तेज है (!)

%option 8bit main fast
%%
.*  { printf("'%s'",yytext); }
\n/(.|\n) { printf(", "); }

लेकिन अगर सिर्फ सभ्य प्रदर्शन स्वीकार्य है (और यदि आप एक तनाव परीक्षण नहीं चला रहे हैं, तो आप किसी भी निरंतर-कारक अंतर को मापने में सक्षम नहीं होंगे, वे सभी तत्काल हैं) और आप अपने विभाजक और उचित दोनों के साथ लचीलापन चाहते हैं -liner-y-सत्ता,

sed "s/.*/'&'/;H;1h;"'$!d;x;s/\n/, /g'

आपका टिकट है हां, यह रेखा के शोर की तरह दिखता है, लेकिन H;1h;$!d;xमुहावरा सब कुछ खत्म करने का सही तरीका है, एक बार जब आप पहचान सकते हैं कि पूरी बात वास्तव में पढ़ने में आसान हो जाती है, तो यह s/.*/'&'/एक थप्पड़ और एक के बाद हैs/\n/, /g


संपादित करें: बेतुकी सीमा पर, हर चीज को खोखला करने के लिए फ्लेक्स प्राप्त करना काफी आसान है, बस stdio को बताएं कि आपको बिल्टिन मल्टीथ्रेड / सिग्नलहैंडलर सिंक की आवश्यकता नहीं है:

%option 8bit main fast
%%
.+  { putchar_unlocked('\'');
      fwrite_unlocked(yytext,yyleng,1,stdout);
      putchar_unlocked('\''); }
\n/(.|\n) { fwrite_unlocked(", ",2,1,stdout); }

और तनाव के तहत पेस्ट पाइपलाइनों की तुलना में 2-3 गुना तेज है, जो खुद को बाकी चीजों की तुलना में कम से कम 5x तेज है।


1
(paste -d\ \'\' /dev/null /dev/null - /dev/null | paste -sd, -) <infile | cut -c2-कॉमा + अंतरिक्ष @ बहुत अधिक गति करेगा जैसा कि आपने उल्लेख किया है, यह वास्तव में लचीला नहीं है यदि आपको विभाजक के रूप में कुछ फैंसी स्ट्रिंग की आवश्यकता है
don_crissti

यह flexसामान बहुत अच्छा आदमी है ... यह पहली बार है जब मैंने किसी flexको इस साइट पर कोड पोस्ट करते हुए देखा ... बड़ा अपवोट! कृपया इस सामग्री को अधिक पोस्ट करें।
don_crissti

@don_crissti धन्यवाद! मैं अच्छे अवसरों की तलाश में हूँ, sed / awk / whatnot आमतौर पर सुविधा मूल्य के लिए बेहतर विकल्प हैं, लेकिन अक्सर एक बहुत ही आसान फ्लेक्स उत्तर भी होता है।
jthill

4

पर्ल

पायथन वन-लाइनर:

$ python -c "import sys; print ','.join([repr(l.strip()) for l in sys.stdin])" < input.txt                               
'd3heatmap','data.table','ggplot2','htmltools','htmlwidgets','metricsgraphics','networkD3','plotly','reshape2','scales','stringr'

सरल तरीके से काम करता है - हम शेल के <संचालक का उपयोग करके इनपुट में टेक्स्ट को रीडायरेक्ट करते हैं। प्रत्येक पंक्ति .strip()को नई लिस्ट से हटाते हैं और repr()प्रत्येक पंक्ति के उद्धृत प्रतिनिधित्व का निर्माण करते हैं। फिर सूची को .join()फ़ंक्शन के माध्यम से एक बड़ी स्ट्रिंग में शामिल किया गया है, को विभाजक के रूप में

वैकल्पिक रूप से हम +प्रत्येक छीनने वाली पंक्ति के उद्धरण का उपयोग कर सकते हैं ।

 python -c "import sys;sq='\'';print ','.join([sq+l.strip()+sq for l in sys.stdin])" < input.txt

पर्ल

पहले की तरह अनिवार्य रूप से एक ही विचार: सभी पंक्तियों को पढ़ें, पट्टी अनुगामी नई रेखा, एकल उद्धरणों में संलग्न करें, सब कुछ सरणी @cvs में भरें, और अल्पविराम के साथ शामिल किए गए सरणी मानों को प्रिंट करें।

$ perl -ne 'chomp; $sq = "\047" ; push @cvs,"$sq$_$sq";END{ print join(",",@cvs)   }'  input.txt                        

'D3heatmap', 'data.table', 'ggplot2', 'htmltools', 'htmlwidgets', 'metricsgraphics', 'networkD3', 'plotly', 'reshape2', 'तराजू', 'stringr'


IIRC, join
अजगरों

@iruvar हां, ओपी के वांछित आउटपुट को छोड़कर - वे प्रत्येक शब्द को उद्धृत करना चाहते हैं, और आउटपुट को सुनिश्चित करने के लिए हमें अनुगामी newlines को निकालने की आवश्यकता है। आपके पास एक विचार है कि सूची समझ के बिना ऐसा कैसे करें?
सर्गी कोलोडियाज़नी

3

मुझे लगता है कि निम्नलिखित को ठीक करना चाहिए, यह मानते हुए कि आप डेटा फ़ाइल फ़ाइल में हैं

d3heatmap
data.table
ggplot2
htmltools
htmlwidgets
metricsgraphics
networkD3
plotly
reshape2
scales
stringr

आइए उन सरणियों का उपयोग करें जिनके पास ठंड का प्रतिस्थापन है:

#!/bin/bash
input=( $(cat text) ) 
output=( $(
for i in ${input[@]}
        do
        echo -ne "'$i',"
done
) )
output=${output:0:-1}
echo ${output//,/, }

स्क्रिप्ट का आउटपुट निम्नानुसार होना चाहिए:

'd3heatmap', 'data.table', 'ggplot2', 'htmltools', 'htmlwidgets', 'metricsgraphics', 'networkD3', 'plotly', 'reshape2', 'scales', 'stringr'

मेरा मानना ​​है कि यह वही था जो आप ढूंढ रहे थे?


1
अच्छा समाधान है। लेकिन जबकि ओपी ने स्पष्ट रूप से नहीं पूछा था bashऔर जबकि यह मान लेना सुरक्षित है कि कोई इसका उपयोग कर सकता है (सभी AFAIK के बाद यह सबसे अधिक उपयोग किया जाने वाला शेल है) इसे अभी भी नहीं लिया जाना चाहिए। इसके अलावा, ऐसे हिस्से हैं जिन्हें आप उद्धृत करने (दोहरे उद्धरणों में डालते हुए) पर बेहतर काम कर सकते हैं। उदाहरण के लिए, जबकि पैकेज के नामों में रिक्त स्थान होने की संभावना नहीं है, यह अभी भी चर को उद्धृत करने के लिए अच्छा सम्मेलन है, न कि आप इसके ऊपर shellcheck.net चलाना चाहते हैं और वहां नोट्स और स्पष्टीकरण देख सकते हैं।
phk

2

मेरे पास अक्सर एक समान परिदृश्य होता है: मैं एक्सेल से एक कॉलम की प्रतिलिपि बनाता हूं और सामग्री को अल्पविराम से अलग की गई सूची में बदलना चाहता हूं (जैसे कि SQL क्वेरी में बाद के उपयोग के लिए ... WHERE col_name IN <comma-separated-list-here>)।

यह मेरे .bashrc में है:

function lbl {
    TMPFILE=$(mktemp)
    cat $1 > $TMPFILE
    dos2unix $TMPFILE
    (echo "("; cat $TMPFILE; echo ")") | tr '\n' ',' | sed -e 's/(,/(/' -e 's/,)/)/' -e 's/),/)/'
    rm $TMPFILE
}

मैं तब lblcmd लाइन पर "(लाइन द्वारा लाइन") चलाता हूं जो इनपुट की प्रतीक्षा करता है, क्लिपबोर्ड से सामग्री को चिपकाता है, प्रेस करता है <C-D>और फ़ंक्शन इनपुट से घिरा हुआ रिटर्न देता है ()। ऐसा दिखता है:

$ lbl
1
2
3
dos2unix: converting file /tmp/tmp.OGM6UahLTE to Unix format ...
(1,2,3)

(मुझे याद नहीं है कि मैंने dos2unix को यहां क्यों रखा है, शायद इसलिए क्योंकि यह अक्सर मेरी कंपनी के सेटअप में परेशानी का कारण बनता है।)


1

Sed के कुछ संस्करण थोड़ा अलग काम करते हैं, लेकिन मेरे मैक पर, मैं सब कुछ संभाल सकता हूं, लेकिन sed में "uniq":

sed -n -e '
# Skip commented library lines
/#/b
# Handle library lines
/library(/{
    # Replace line with just quoted filename and comma
    # Extra quoting is due to command-line use of a quote
    s/library(\([^)]*\))/'\''\1'\'', /
    # Exchange with hold, append new entry, remove the new-line
    x; G; s/\n//
    ${
        # If last line, remove trailing comma, print, quit
        s/, $//; p; b
    }
    # Save into hold
    x
}
${
    # Last line not library
    # Exchange with hold, remove trailing comma, print
    x; s/, $//; p
}
'

दुर्भाग्य से कुछ करने के लिए अद्वितीय भाग को ठीक करने के लिए:

grep library Presentation.md | sort -u | sed -n -e '...'

--Paul


2
Unix.stackexchange में आपका स्वागत है! मैं आपको दौरे लेने की सलाह देता हूं ।
स्टीफन राउच

0

यह हास्यास्पद है कि आर पैकेज में उन्हें स्थापित करने के लिए आर संकुल की एक सादे पाठ सूची का उपयोग करने के लिए, किसी ने सीधे आर में उस सूची का उपयोग करके समाधान का प्रस्ताव नहीं किया, लेकिन बैश, पर्ल, अजगर, awk, sed या जो भी उद्धरण और अल्पविराम लगाने के लिए लड़ें। सूची। यह बिल्कुल भी आवश्यक नहीं है और इसके अलावा यह पता नहीं चलता है कि आर में रूपांतरित सूची का इनपुट और उपयोग कैसे किया जाता है।

आप केवल packages.txtएक ही चर के साथ डेटाफ्रेम के रूप में सादे पाठ फ़ाइल (कहा, ) को लोड कर सकते हैं, जिसे आप सीधे वेक्टर के रूप में निकाल सकते हैं install.packages। इसलिए, इसे एक उपयोगी आर ऑब्जेक्ट में परिवर्तित करें और स्थापित करें कि सूची बस है:

df <- read.delim("packages.txt", header=F, strip.white=T, stringsAsFactors=F)
install.packages(df$V1)

या बाहरी फ़ाइल के बिना:

packages <-" 
d3heatmap
data.table
ggplot2
htmltools
htmlwidgets
metricsgraphics
networkD3
plotly
reshape2
scales
stringr
"
df <- read.delim(textConnection(packages), 
header=F, strip.white=T, stringsAsFactors=F)
install.packages(df$V1)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.