मैं हर चार वर्णों को एक लंबी पंक्ति में स्थान कैसे डालूं?


30

मुझे एक लंबी लाइन मिली है जिसे मैं हर 4 अक्षरों में एक जगह सम्मिलित करना चाहता हूं, ठोस पाठ की एक अकेली लाइन पर इसे पढ़ना आसान है, ऐसा करने का सबसे सरल तरीका क्या है? मैं भी एक पाइप से लाइन इनपुट करने में सक्षम होना चाहिए। जैसे

echo "foobarbazblargblurg" | <some command here>

देता है

foob arba zbla rgbl urg

जवाबों:


54

निम्नानुसार सेड का प्रयोग करें:

$ echo "foobarbazblargblurg" | sed 's/.\{4\}/& /g'
foob arba zbla rgbl urg

1
यह शाप कि sedमैं पहले कोशिश कर रहा था के करीब था, मैं खुद को लात मार सकता था।
xenoterracide

7
बस जिज्ञासु, क्या 'और' की उपलब्धि है? ओह, यह 'बस क्या मिला' वाली बात है। मुझे मूर्ख।
सर्वार्थसिद्ध

1
यह ध्यान दिया जाना चाहिए कि यह अंत में एक स्थान जोड़ता है यदि स्ट्रिंग में एक और चरित्र है, जो वांछनीय नहीं हो सकता है
Anubis

@ अब्निस's/.\{4\}/& /g;s/ $//'
wieczorek1990

21

आप निम्नलिखित सरल उदाहरण का उपयोग कर सकते हैं:

$ echo "foobarbazblargblurg" | fold -w4 | paste -sd' ' -
foob arba zbla rgbl

बहुत अच्छा ... मुझे लगता है कि यह sedउत्तर से भी बेहतर है । मैं पहले नहीं जानता था fold
वाइल्डकार्ड

1
दुर्भाग्य से, जीएनयू के वर्तमान संस्करणों के साथ fold, यह मल्टी-बाइट पात्रों ( echo €€€€€€€€ | fold -w4 | paste -sd' ' -यूटीएफ -8 में) के साथ काम नहीं करता है ।
स्टीफन चेज़लस

3

यहाँ उदाहरण का उपयोग कर रहा है grepऔर xargs:

$ echo "foobarbazblargblurg" | grep -o .... | xargs
foob arba zbla rgbl

xargsechoडिफ़ॉल्ट रूप से चलता है, इसलिए यह क्रियान्वयन के -nenआधार पर बैकस्लैश जैसे शब्दों के साथ काम नहीं करेगा echo। यदि आप xargs एक से अधिक चलाते हैं तो आपको एक बार में विषम न्यूलाइन वर्ण दिखाई देगा echopaste -sd ' ' -इसके बजाय पाइप करने के लिए बेहतर है । ध्यान दें कि -oएक मानक विकल्प नहीं है।
स्टीफन चेज़लस

3

केवल बैश में, कोई बाहरी आदेश नहीं:

str="foobarbazblargblurg"
[[ $str =~ ${str//?/(.)} ]]
printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"

या एक-लाइन पाइप संस्करण के रूप में:

echo foobarbazblargblurg | 
  { IFS= read -r str; [[ $str =~ ${str//?/(.)} ]]; \
    printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"; }

जिस तरह से यह काम करता है वह स्ट्रिंग के प्रत्येक चरित्र को रेगेक्स मैच के लिए "(।)" में परिवर्तित करने और =~फिर कैप्चर करने के लिए होता है , फिर BASH_REMATCH[]आवश्यकता के अनुसार समूह से कैप्चर किए गए एक्सप्रेशंस को आउटपुट करता है। लीडिंग / ट्रेलिंग / इंटरमीडिएट रिक्त स्थान संरक्षित हैं, "${BASH_REMATCH[@]:1}"उन्हें छोड़ने के लिए आसपास के उद्धरण हटा दें ।

यहाँ इसे एक फंक्शन में लपेटा गया है, अगर कोई तर्क नहीं है, तो यह अपने तर्कों को पढ़ेगा या स्टड को पढ़ेगा:

function fmt4() {
  while IFS= read -r str; do
    [[ $str =~ ${str//?/(.)} ]]
    printf "%s%s%s%s " "${BASH_REMATCH[@]:1}"
  done < <( (( $# )) && printf '%s\n' "$@" || printf '%s\n' $(< /dev/stdin) )
}

$ echo foobarbazblargblurg | fmt4
foob arba zbla rgbl urg 

आप प्रारूप स्ट्रिंग को तदनुसार समायोजित करने के लिए आसानी से गणना को पैरामीटर कर सकते हैं।

एक अनुगामी स्थान जोड़ा जाता है, printfयदि समस्या है तो एक के बजाय दो एस का उपयोग करें :

printf "%s%s%s%s" "${BASH_REMATCH[@]:1:4}"
(( ${#BASH_REMATCH[@]} > 5 )) && printf " %s%s%s%s" "${BASH_REMATCH[@]:5}"

printfपहले 4 अक्षरों के लिए पहला प्रिंट (दूसरा), दूसरा सशर्त सभी (यदि कोई है) समूहों को अलग करने के लिए एक अग्रणी स्थान के साथ प्रिंट करता है। परीक्षण 5 तत्वों के लिए है न कि 4 शून्य तत्व के लिए।

टिप्पणियाँ:

  • शेल printfका %cउपयोग इसके बजाय किया जा सकता है %s, %c(हो सकता है) इरादे को स्पष्ट करता है, लेकिन यह बहु-बाइट वर्ण सुरक्षित नहीं है। यदि आपका बैश का संस्करण सक्षम है, तो उपरोक्त सभी मल्टी-बाइट चरित्र सुरक्षित है।
  • शेल printfअपने प्रारूप स्ट्रिंग का तब तक पुन: उपयोग करता है जब तक कि वह तर्कों से बाहर नहीं निकल जाता है, इसलिए यह एक बार में 4 तर्कों को पकड़ लेता है, और अनुगामी तर्कों को संभालता है (इसलिए कोई किनारे के मामलों की आवश्यकता नहीं है, यहां कुछ अन्य उत्तरों के विपरीत जो यकीनन गलत हैं)
  • BASH_REMATCH[0] संपूर्ण मिलान स्ट्रिंग है, इसलिए केवल इंडेक्स 1 से शुरू होने वाला आउटपुट
  • printf -v myvar ...एक वैरिएबल को स्टोर करने के बजाय उपयोग करें myvar(सामान्य रीड-लूप / सब्स्क्रिप्शन व्यवहार के अधीन)
  • printf "\n"यदि आवश्यक हो तो जोड़ें

zshयदि आप match[]इसके बजाय सरणी का उपयोग करते हैं, तो आप उपरोक्त कार्य कर सकते हैं BASH_REMATCH[], और सभी अनुक्रमितों में से 1 घटा zshसकते हैं क्योंकि पूरे मैच में 0 तत्व नहीं है।


3

zshकेवल साथ :

str=foobarbazblargblurg

set -o extendedglob
printf '%s\n' ${str//(#m)????/$MATCH }

या

printf '%s%s%s%s ' ${(s::)str}

ksh93केवल साथ :

printf '%s\n' "${str//????/\0 }"

केवल किसी POSIX शेल के साथ (यदि इनपुट लंबाई 4 से अधिक है, तो अनुगामी स्थान से बचना)

out=
while true; do
  case $str in
    (?????*)
      new_str=${str#????}
      out=$out${str%"$new_str"}' '
      str=$new_str
      ;;
    (*)
      out=$out$str
      break
  esac
done
printf '%s\n' "$out"

अब, यह पात्रों के लिए है । यदि आप इसे अंगूर के समूहों पर करना चाहते हैं (उदाहरण के लिए, तोड़ने के लिए Stéphane, जैसा $'Ste\u0301phane', जैसा Stép haneऔर न लिखा जाए Ste phan e), साथ zsh:

set -o rematchpcre
str=$'Ste\u301phane' out=
while [[ $str =~ '(\X{4})(.+)' ]] {
  out+="$match[1] " str=$match[2]
}
out+=$str
printf '%s\n' $out

Ksh93 के साथ, आप प्रदर्शन चौड़ाई के अनुसार भी तोड़ सकते हैं, जो Stéphaneऊपर दिए गए कार्यों के लिए काम करेगा , लेकिन कुछ अन्य प्रकार के शून्य-चौड़ाई या दोहरे-चौड़ाई वाले वर्ण शामिल होने पर भी मदद कर सकता है:

str=$'Ste\u301phane' out=
while
  start=${ printf %L.4s. "$str"; }
  start=${start%.}
  [ "$start" != "$str" ]
do
  out+="$start " str=${str#"$start"}
done
out+=$str
printf '%s\n' "$out"

2

मैं केवल आवश्यक स्थानों को सम्मिलित करके उत्तर देने जा रहा हूं ताकि एक पंक्ति में प्रत्येक 4 वर्णों के बाद कम से कम एक स्थान दिखाई दे; निश्चित नहीं है कि आप इस मामले को किस तरह से हैंडल करना चाहते हैं। उदाहरण के लिए, "आ bbccdd" का दिया गया इनपुट, आपको "आ ब बक्का डी" के बजाय आउटपुट "आ bbcc dd" मिलेगा।

मैं पर्ल का उपयोग लुकहेड के लिए कर रहा हूं, लेकिन मैं पर्ल के साथ सामान्य रूप से परिचित नहीं हूं, इसलिए इसमें ट्वीक की जरूरत हो सकती है:

$ echo "foobarbazblargblurg" | perl -wp -e 's/[^ ]{4}(?=[^\n ])/$& /g'
foob arba zbla rgbl urg

$ echo 'aa bbccdd' | perl -wp -e 's/[^ ]{4}(?=[^\n ])/$& /g'
aa bbcc dd
# not 'aa b bccd d'!

$ echo 'some input' | perl -wp -e 's/[^ ]{4}(?=[^\n ])/$& /g'
some inpu t
# not 'some  inp ut'!

$ echo $'aabb\nc cddee' | perl -wp -e 's/[^ ]{4}(?=[^\n ])/$& /g' | 
> while read; do echo "${REPLY}x"; done
aabbx
c cdde ex
# no spaces added at the end of the first line (while loop to add to the end of
# the line and show this)

0

मैंने अजगर का उपयोग करके ऐसा किया है

पहले मैं फ़ाइल पढ़ रहा हूं फिर मैं 4 वर्णों को विभाजित कर रहा हूं और स्थान जोड़ रहा हूं

#!/usr/bin/python
import re
b=re.compile(r'[a-z]{4}')

p=open('/root/l.txt','r')
i=p.readlines()
for j in i:
    m=re.findall(b,j)
print " " .join (m) + "  "

/root/l.txt ==> उदाहरण में दी गई सामग्री से युक्त

उत्पादन

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