मैं एक शब्द के अक्षरों को अलग लाइन में प्रत्येक अक्षर के साथ कैसे विभाजित कर सकता हूं?
उदाहरण के लिए, "StackOver"
मैं देखना चाहूंगा
S
t
a
c
k
O
v
e
r
मैं बैश करने के लिए नया हूं इसलिए मुझे कोई सुराग नहीं है कि कहां से शुरू करें।
मैं एक शब्द के अक्षरों को अलग लाइन में प्रत्येक अक्षर के साथ कैसे विभाजित कर सकता हूं?
उदाहरण के लिए, "StackOver"
मैं देखना चाहूंगा
S
t
a
c
k
O
v
e
r
मैं बैश करने के लिए नया हूं इसलिए मुझे कोई सुराग नहीं है कि कहां से शुरू करें।
जवाबों:
मैं उपयोग करेगा 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 ग्रहण करते हैं।
Here string
, ग्रोसो मोडो echo foo | ...
सिर्फ कम टाइपिंग के बराबर । देखें tldp.org/LDP/abs/html/x17837.html
.
होता है \B
(शब्द सीमा पर मेल नहीं खाता)।
sed
जैसे:sed -et -e's/./\n&/g;//D'
यदि आप टेक्स्ट को प्रिंट करने का इरादा रखते हैं, तो आप वर्णों के बजाय अंगूर के समूहों को तोड़ सकते हैं। उदाहरण के लिए 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'
)
कई awk
संस्करणों के साथ
awk -F '' -v OFS='\n' '{$1=$1};1' <<<'StackOver'
awk -v FS='' -v OFS='\n' '{$1=$1};1'
(सोच रहा है कि अगर अधिक पोर्टेबल है, क्योंकि -F ''
ERE देगा: //
)
नीचे सामान्य होगा:
$ awk -F '' \
'BEGIN { RS = ""; OFS = "\n"} {for (i=1;i<=NF;i++) $i = $i; print }' <file_name>
चूंकि आपने विशेष रूप से बैश में जवाब मांगा था, इसलिए इसे शुद्ध बैश में करने का एक तरीका है:
while read -rn1; do echo "$REPLY" ; done <<< "StackOver"
ध्यान दें कि यह " यहां दस्तावेज़ " के अंत में नई रेखा को पकड़ेगा । यदि आप उससे बचना चाहते हैं, लेकिन फिर भी बैश लूप वाले पात्रों पर पुनरावृति करते हैं, printf
तो न्यूलाइन से बचने के लिए उपयोग करें।
printf StackOver | while read -rn1; do echo "$REPLY" ; done
इसके अलावा पायथन 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')"
आप 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
$
आप मल्टीबाइट पात्रों को संभाल सकते हैं जैसे:
<input \
dd cbs=1 obs=2 conv=unblock |
sed -e:c -e '/^.*$/!N;s/\n//;tc'
जब आप लाइव इनपुट के साथ काम कर रहे हों, तो यह बहुत आसान हो सकता है क्योंकि वहां कोई बफरिंग नहीं है और एक कैरेक्टर प्रिंट होते ही पूरा हो जाता है ।
sed
स्क्रिप्ट के लिए है। मैं अब के बारे में एक सही लिखने की संभावना नहीं हूँ - सुंदर नींद im। यह वास्तव में उपयोगी है, हालांकि, जब एक टर्मिनल पढ़ना।
dd
मल्टीबीट वर्णों को तोड़ देगा, इसलिए आउटपुट अब पाठ नहीं होगा, इसलिए पीओएसआईएक्स के अनुसार सेड का व्यवहार अनिर्दिष्ट होगा।
आप शब्द सीमाओं का भी उपयोग कर सकते हैं।
$ perl -pe 's/(?<=.)(\B|\b)(?=.)/\n/g' <<< "StackOver"
S
t
a
c
k
O
v
e
r
बैश में:
यह किसी भी पाठ के साथ और केवल बैश इंटर्नल्स (कोई बाहरी उपयोगिता नहीं कहा जाता है) के साथ काम करता है, इसलिए, बहुत कम तारों पर तेज होना चाहिए।
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 "$*"
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
}
read -a var <<< $(echo "$yourWordhere" | grep -o "." | tr '\n' ' ')
यह आपके शब्द को विभाजित करेगा और इसे सरणी में संग्रहीत करेगा var
।
for x in $(echo "$yourWordhere" | grep -o '.')
do
code to perform operation on individual character $x of your word
done