बैश स्क्रिप्ट: प्रत्येक अक्षर पर विभाजित शब्द


17

मैं एक शब्द के अक्षरों को अलग लाइन में प्रत्येक अक्षर के साथ कैसे विभाजित कर सकता हूं?

उदाहरण के लिए, "StackOver" मैं देखना चाहूंगा

S
t
a
c
k
O
v
e
r

मैं बैश करने के लिए नया हूं इसलिए मुझे कोई सुराग नहीं है कि कहां से शुरू करें।

जवाबों:


29

मैं उपयोग करेगा grep:

$ grep -o . <<<"StackOver"
S
t
a
c
k
O
v
e
r

या sed:

$ sed 's/./&\n/g' <<<"StackOver"
S
t
a
c
k
O
v
e
r

और अगर अंत में खाली जगह एक मुद्दा है:

sed 's/\B/&\n/g' <<<"StackOver"

कि सभी GNU / Linux ग्रहण करते हैं।


grep -o <<< for <¿..-PATTERN के लिए खोज सही प्रदान की है? और यह आपकी आज्ञा में यहाँ क्या करता है?
सिजान हालक

1
@ जिमीज मैं कठबोली <<< वास्तव में क्या करता है पर कोई मदद मिल सकती है! कोई मदद?
10 बजकर 50 मिनट पर सिज़ान हालक

3
@SijaanHallak यह तथाकथित है Here string, ग्रोसो मोडो echo foo | ...सिर्फ कम टाइपिंग के बराबर । देखें tldp.org/LDP/abs/html/x17837.html
jimmij

1
@SijaanHallak में परिवर्तन .होता है \B(शब्द सीमा पर मेल नहीं खाता)।
जिमीज

1
@ शिजानहल्क - आप दूसरा गिरा सकते हैं sedजैसे:sed -et -e's/./\n&/g;//D'
mikeserv

19

यदि आप टेक्स्ट को प्रिंट करने का इरादा रखते हैं, तो आप वर्णों के बजाय अंगूर के समूहों को तोड़ सकते हैं। उदाहरण के लिए eएक तीव्र उच्चारण के साथ:

  • अंगूर के समूहों के eसाथ ( इसके तीव्र उच्चारण में एक अंगूर समूह होगा):

    $ perl -CLAS -le 'for (@ARGV) {print for /\X/g}' $'Ste\u301phane'
    S
    t
    é
    p
    h
    a
    n
    e
    

    (या grep -Po '\X'पीसीआरई समर्थन के साथ निर्मित GNU grep के साथ)

  • पात्रों के साथ (यहाँ GNU के साथ grep):

    $ printf '%s\n' $'Ste\u301phane' | grep -o .
    S
    t
    e
    
    p
    h
    a
    n
    e
    
  • foldवर्णों पर विराम लगाने के लिए है, लेकिन GNU foldमल्टी-बाइट वर्णों का समर्थन नहीं करता है, इसलिए यह बाइट्स पर टूट जाता है:

    $ printf '%s\n' $'Ste\u301phane' | fold -w 1
    S
    t
    e
    �
    �
    p
    h
    a
    n
    e
    

पर StackOver जो केवल ASCII वर्ण हैं (ताकि चरित्र प्रति एक बाइट, ग्रफीम क्लस्टर प्रति एक चरित्र), सभी तीन एक ही परिणाम देना होगा।


मुझे आश्चर्य है grep -Poकि कोई ऐसा नहीं करेगा जो उम्मीद grep -Pकरता है (जैसे करता है)।
जिमीज ५'१६ को

@ जिमीज, आपका क्या मतलब है? grep -Po .वर्ण पाता है (और एक नई grep -Po '\X'पंक्ति के बाद तीव्र उच्चारण एक संयोजन अमान्य है), और मेरे लिए अंगूर के गुच्छों को ढूंढता है। ठीक से काम करने के लिए आपको grep और / या PCRE के हाल के संस्करण की आवश्यकता हो सकती है (या कोशिश करें grep -Po '(*UTF8)\X')
स्टीफन चेज़लस

2
@SijaanHallak ये मददगार हो सकते हैं: joelonsoftware.com/articles/Unicode.html , eev.ee/blog/2015/09/12/dark-corners-of-unicode
jpmc26

6

यदि आपके बॉक्स में perl6 है:

$ perl6 -e 'for @*ARGS -> $w { .say for $w.comb }' 'cường'       
c
ư
ờ
n
g

अपने लोकल की परवाह किए बिना काम करें।


6

कई awkसंस्करणों के साथ

awk -F '' -v OFS='\n' '{$1=$1};1' <<<'StackOver'

महान! लेकिन nAWK ("वन ट्रू एडब्ल्यूके") के मेरे संस्करण पर जो काम नहीं करता है। हालांकि इस काम कर देता है: awk -v FS='' -v OFS='\n' '{$1=$1};1' (सोच रहा है कि अगर अधिक पोर्टेबल है, क्योंकि -F ''ERE देगा: //)
eruve

4

नीचे सामान्य होगा:

$ awk -F '' \
   'BEGIN { RS = ""; OFS = "\n"} {for (i=1;i<=NF;i++) $i = $i; print }' <file_name>


4

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

while read -rn1; do echo "$REPLY" ; done <<< "StackOver"

ध्यान दें कि यह " यहां दस्तावेज़ " के अंत में नई रेखा को पकड़ेगा । यदि आप उससे बचना चाहते हैं, लेकिन फिर भी बैश लूप वाले पात्रों पर पुनरावृति करते हैं, printfतो न्यूलाइन से बचने के लिए उपयोग करें।

printf StackOver | while read -rn1; do echo "$REPLY" ; done

4

इसके अलावा पायथन 2 का इस्तेमाल कमांड लाइन से किया जा सकता है:

python <<< "for x in 'StackOver':
   print x"

या:

echo "for x in 'StackOver':
    print x" | python

या (1_CR द्वारा टिप्पणी के रूप में) पायथन 3 के साथ :

python3 -c "print(*'StackOver',sep='\n')"

4

आप fold (1)कमांड का उपयोग कर सकते हैं । यह की तुलना में अधिक कुशल है grepऔर sed

$ time grep -o . <bigfile >/dev/null

real    0m3.868s
user    0m3.784s
sys     0m0.056s
$ time fold -b1 <bigfile >/dev/null

real    0m0.555s
user    0m0.528s
sys     0m0.016s
$

एक महत्वपूर्ण अंतर यह है कि गुना आउटपुट में खाली लाइनों को पुन: पेश करेगा:

$ grep -o . <(printf "A\nB\n\nC\n\n\nD\n")
A
B
C
D
$ fold -b1 <(printf "A\nB\n\nC\n\n\nD\n")
A
B

C


D
$ 

3

आप मल्टीबाइट पात्रों को संभाल सकते हैं जैसे:

<input \
dd cbs=1 obs=2 conv=unblock |
sed -e:c -e '/^.*$/!N;s/\n//;tc'

जब आप लाइव इनपुट के साथ काम कर रहे हों, तो यह बहुत आसान हो सकता है क्योंकि वहां कोई बफरिंग नहीं है और एक कैरेक्टर प्रिंट होते ही पूरा हो जाता है ।


एनपी, क्या हमें लोकेल के बारे में एक नोट जोड़ना चाहिए?
कोउंगलम

स्टीफन चेज़लस जैसे पात्रों के संयोजन के लिए काम नहीं करता है, लेकिन उचित सामान्यीकरण के साथ यह बात नहीं होनी चाहिए।
- एसई बुराई है

@Kay - यदि आप चाहते हैं तो यह पात्रों के संयोजन के लिए काम करता है - यही sedस्क्रिप्ट के लिए है। मैं अब के बारे में एक सही लिखने की संभावना नहीं हूँ - सुंदर नींद im। यह वास्तव में उपयोगी है, हालांकि, जब एक टर्मिनल पढ़ना।
14

@cuonglm - अगर आपको पसंद है। यह सिर्फ स्थानीय लोगों के लिए काम करना चाहिए, हालांकि एक समझदार काम दिया जाता है।
15

ध्यान दें कि ddमल्टीबीट वर्णों को तोड़ देगा, इसलिए आउटपुट अब पाठ नहीं होगा, इसलिए पीओएसआईएक्स के अनुसार सेड का व्यवहार अनिर्दिष्ट होगा।
स्टीफन चेज़लस

3

आप शब्द सीमाओं का भी उपयोग कर सकते हैं।

$ perl -pe 's/(?<=.)(\B|\b)(?=.)/\n/g' <<< "StackOver"
S
t
a
c
k
O
v
e
r

1

बैश में:

यह किसी भी पाठ के साथ और केवल बैश इंटर्नल्स (कोई बाहरी उपयोगिता नहीं कहा जाता है) के साथ काम करता है, इसलिए, बहुत कम तारों पर तेज होना चाहिए।

str="Stéphane áàéèëêếe"

[[ $str =~ ${str//?/(.)} ]]
(set -- "${BASH_REMATCH[@]:1}"; IFS=$'\n'; echo "$*")

आउटपुट:

S
t
é
p
h
a
n
e

á
à
é
è
ë
ê
ế
e

यदि IFS को बदलना और स्थिति मापदंडों को बदलना ठीक है, तो आप उप-शेल कॉल से भी बच सकते हैं:

str="Stéphane áàéèëêếe"
[[ $str =~ ${str//?/(.)} ]]
set -- "${BASH_REMATCH[@]:1}"
IFS=$'\n'
echo "$*"

1
s=stackoverflow;

$ time echo $s | fold -w1                                                                                                                                          
s                                                                                                                                                                          
t                                                                                                                                                                          
a                                                                                                                                                                          
c                                                                                                                                                                          
k                                                                                                                                                                          
o                                                                                                                                                                          
v
e
r

real    0m0.014s
user    0m0.000s
sys     0m0.004s

यहाँ अद्यतन हैक है | सबसे तेज़ |

$ time eval eval printf \'%s\\\\n\' \\\${s:\{0..$((${#s}-1))}:1}
s
t
a
c
k
o
v
e
r

real    0m0.001s
user    0m0.000s
sys     0m0.000s

अधिक अजीबता के लिए

function foldh () 
{ 
    if (($#)); then
        local s="$@";
        eval eval printf \'%s\\\\n\' \\\"\\\${s:\{0..$((${#s}-1))}:1}\\\";
    else
        while read s; do
            eval eval printf \'%s\\\\n\' \\\"\\\${s:\{0..$((${#s}-1))}:1}\\\";
        done;
    fi
}
function foldv () 
{ 
    if (($#)); then
        local s="$@";
        eval eval echo \\\"\\\${s:\{0..$((${#s}-1))}:1}\\\";
    else
        while read s; do
            eval eval echo \\\"\\\${s:\{0..$((${#s}-1))}:1}\\\";
        done;
    fi
}

क्या यह कभी अलग परिणाम देगा fold -b1?
जिगलीनागा

चूंकि प्रत्येक बाइट की चौड़ाई = 1 होती है, इसलिए परिणाम समान होगा!
जोनाह

1
तो यह पहले के उत्तर की नकल कैसे नहीं है ?
जिगलीनाग

क्योंकि यह tha एक ही cmd को अलग अलग दिखावे के साथ दिखाता है, और यह जानना अच्छा है।
जोनाह

1
read -a var <<< $(echo "$yourWordhere" | grep -o "." | tr '\n' ' ')

यह आपके शब्द को विभाजित करेगा और इसे सरणी में संग्रहीत करेगा var


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.