वर्णों की एक स्ट्रिंग की प्रदर्शन चौड़ाई प्राप्त करें


15

एक शेल स्क्रिप्ट से वर्णों की एक स्ट्रिंग के प्रदर्शन की चौड़ाई (कम से कम एक टर्मिनल पर सही चौड़ाई के साथ वर्तमान लोकेल में प्रदर्शित करता है) पाने के लिए पोर्टेबल तरीके के सबसे करीब क्या होगा।

मैं मुख्य रूप से गैर-नियंत्रण वर्णों की चौड़ाई में दिलचस्पी रखता हूं, लेकिन समाधान जो बैकस्पेस, कैरिज रिटर्न, क्षैतिज सारणीकरण जैसे नियंत्रण पात्रों को ध्यान में रखते हैं, उनका भी स्वागत है।

दूसरे शब्दों में, मैं POSIX फ़ंक्शन के आसपास एक शेल एपीआई की तलाश कर रहा हूं wcswidth()

वह आदेश वापस आ जाना चाहिए:

$ that-command 'unix'   # 4 fullwidth characters
8
$ that-command 'Stéphane' # 9 characters, one of which zero-width
8
$ that-command 'もで 諤奯ゞ' # 5 double-width Japanese characters and a space
11

एक इस्तेमाल कर सकते हैं ksh93s ' printf '%<n>Ls'को ध्यान में करने के लिए गद्दी के लिए वर्ण चौड़ाई लेता <n>कॉलम, या col(उदाहरण के लिए के साथ आदेश printf '++%s\b\b--\n' <character> | col -b) कोशिश करते हैं और है कि प्राप्त करने के लिए, वहाँ एक पाठ है :: CharWidth perlकम से कम मॉड्यूल, लेकिन वहाँ और अधिक प्रत्यक्ष या पोर्टेबल दृष्टिकोण हैं।

यह कमोबेश उस अन्य प्रश्न पर अनुवर्ती है जो स्क्रीन के दाईं ओर पाठ प्रदर्शित करने के बारे में था, जिसके लिए आपको पाठ प्रदर्शित करने से पहले उस जानकारी की आवश्यकता होगी।


जवाबों:


7

एक टर्मिनल एमुलेटर में, कोई भी स्थिति से पहले / बाद में प्राप्त करने के लिए कर्सर स्थिति रिपोर्ट का उपयोग कर सकता है, जैसे, से

...record position
printf '%s' $string
...record position

और टर्मिनल पर छपे वर्णों को कितना व्यापक पाते हैं। चूँकि वह ECMA-48 (साथ ही VT100) नियंत्रण अनुक्रम है जो आपके द्वारा उपयोग किए जाने वाले लगभग किसी भी टर्मिनल द्वारा समर्थित है, यह काफी पोर्टेबल है।

सन्दर्भ के लिए

    CSI Ps n डिवाइस स्थिति रिपोर्ट (DSR)।
              ...
                Ps = 6 -> रिपोर्ट कर्सर स्थिति (CPR) [पंक्ति; स्तंभ]।
              परिणाम CSI r है; सी आर

अंततः, इन कारकों के कारण टर्मिनल एमुलेटर प्रिंट करने योग्य चौड़ाई निर्धारित करता है:

  • लोकल सेटिंग्स उस तरह से प्रभावित करती हैं जिस तरह से एक स्ट्रिंग को स्वरूपित किया जा सकता है, लेकिन टर्मिनल को भेजी जाने वाली बाइट्स की श्रृंखला की व्याख्या इस आधार पर की जाती है कि टर्मिनल कैसे कॉन्फ़िगर किया गया है (यह देखते हुए कि कुछ लोग तर्क देंगे कि इसे UTF-8 होना चाहिए, जबकि दूसरी तरफ पोर्टेबिलिटी प्रश्न में मांगी गई विशेषता थी)।
  • wcswidthअकेले यह नहीं बताता कि संयोजन पात्रों को कैसे संभाला जाता है; POSIX उस फ़ंक्शन के विवरण में इस पहलू का उल्लेख नहीं करता है।
  • कुछ वर्ण (उदाहरण के लिए रेखा-चित्रण) जो किसी को एकल-चौड़ाई के रूप में दिए जा सकते हैं (यूनिकोड में) "अस्पष्ट चौड़ाई", wcswidthअकेले उपयोग करने वाले किसी अनुप्रयोग की पोर्टेबिलिटी को कम करके (उदाहरण के लिए अध्याय 2 देखें )। xtermउदाहरण के लिए, इसके लिए आवश्यक विन्यास के लिए दोहरे-चौड़ाई के पात्रों का चयन करने का प्रावधान है।
  • प्रिंट करने योग्य पात्रों के अलावा कुछ भी संभालने के लिए, आपको टर्मिनल एमुलेटर पर भरोसा करना होगा (जब तक कि आप उसे अनुकरण नहीं करना चाहते)।

शेल एपीआई कॉलिंग wcswidthअलग-अलग डिग्री के लिए समर्थित हैं:

वे अधिक या कम प्रत्यक्ष हैं: wcswidthपर्ल के मामले में अनुकरण करते हुए, रूबी और पायथन से सी रनटाइम कहते हैं। आप पायथन से भी शाप का उपयोग कर सकते हैं, (जो संयोजन वर्णों को संभालेंगे):

  • सेटअप्टरम का उपयोग करके टर्मिनल को इनिशियलाइज़ करें (स्क्रीन पर कोई टेक्स्ट नहीं लिखा गया है)
  • filterफ़ंक्शन का उपयोग करें (एकल लाइनों के लिए)
  • पंक्ति की शुरुआत में पाठ को ड्रा करें addstr, त्रुटि के लिए जाँच (यदि यह बहुत लंबा है), और फिर अंतिम स्थिति के लिए
  • यदि कमरा है, तो शुरुआती स्थिति को समायोजित करें।
  • कॉल endwin(जो नहीं करना चाहिए refresh)
  • मानक आउटपुट के लिए प्रारंभिक स्थिति के बारे में परिणामी जानकारी लिखें

आउटपुट के लिए शापों का उपयोग करना (बजाय किसी स्क्रिप्ट या सीधे कॉल किए जानकारी वापस भेजने के लिए tput) पूरी लाइन को साफ कर देगा ( filterयह एक लाइन तक सीमित करता है)।


मुझे लगता है कि यह एकमात्र तरीका होना चाहिए, वास्तव में। यदि टर्मिनल दोहरे-चौड़ाई वाले वर्णों का समर्थन नहीं करता है, तो यह बहुत मायने नहीं रखता है कि wcswidth()किसी भी चीज के बारे में क्या कहना है।
mikeserv

व्यवहार में, मेरे पास इस पद्धति के साथ एकमात्र समस्या है plink, जो सेट करता है , TERM=xtermभले ही यह किसी भी नियंत्रण अनुक्रम का जवाब नहीं देता है। लेकिन मैं बहुत विदेशी टर्मिनलों का उपयोग नहीं करता हूं।
गिल्स एसओ- बुराई को रोकें '

धन्यवाद। लेकिन यह विचार था कि टर्मिनल पर स्ट्रिंग प्रदर्शित करने से पहले उस जानकारी को प्राप्त करना है (यह जानने के लिए कि इसे कहाँ प्रदर्शित करना है, यह टर्मिनल के दाईं ओर एक स्ट्रिंग प्रदर्शित करने के बारे में हाल के प्रश्न पर अनुवर्ती है, शायद मुझे यह उल्लेख करना चाहिए था कि हालांकि मेरा असली सवाल यह था कि शेल से wcswidth में कैसे पहुंचा जाए)। @mikeserv, हाँ wcswidth () के बारे में गलत हो सकता है कि एक विशिष्ट टर्मिनल किसी विशेष स्ट्रिंग को कैसे प्रदर्शित करेगा, लेकिन यह उतना ही निकट है जितना आप एक टर्मिनल-इंडिपेंडेंट समाधान प्राप्त कर सकते हैं और यही कि मेरे सिस्टम पर col / ksh-printf का उपयोग होता है।
स्टीफन चेजलस

मुझे इसकी जानकारी है, लेकिन wcswidth कम-पोर्टेबल सुविधाओं के माध्यम से सीधे पहुंच योग्य नहीं है (आप कुछ अनुमान लगाकर पर्ल में ऐसा कर सकते हैं - search.cpan.org/dist/Text-CharWidth/CharWhth.pm देखें ) । रास्ते से दाएं-संरेखित प्रश्न (शायद) स्ट्रिंग को निचले-बाएं में लिखकर और फिर कर्सर-स्थिति और सम्मिलित-नियंत्रण का उपयोग करके इसे निचले-दाएं पर स्थानांतरित करने के लिए बेहतर किया जा सकता है।
थॉमस डिकी 11

1
@ स्टीफनचेज़लस - foldजाहिर तौर पर मल्टी-बाइट और विस्तारित चौड़ाई वर्णों को संभालने के लिए निर्दिष्ट है । यहां बताया गया है कि इसे बैकस्पेस कैसे संभालना चाहिए: लाइन की चौड़ाई की वर्तमान गणना को एक से घटाया जाएगा, हालांकि गिनती कभी भी नकारात्मक नहीं होगी। तह उपयोगिता किसी <backline> से पहले या बाद में <newline> नहीं डालेगी, जब तक कि निम्न वर्ण की चौड़ाई 1 से अधिक न हो और पंक्ति की चौड़ाई चौड़ाई से अधिक हो। हो सकता है fold -w[num]और pr +[num]किसी भी तरह मिलकर किया जा सकता है?
मोकेसर

5

वन-लाइन स्ट्रिंग्स के लिए, GNU कार्यान्वयन wcमें एक -L(उर्फ --max-line-length) विकल्प होता है, जो वास्तव में वही है जो आप देख रहे हैं (नियंत्रण चार्ट को छोड़कर)।


1
धन्यवाद। मुझे नहीं पता था कि यह डिस्प्ले की चौड़ाई लौटाएगा। ध्यान दें कि FreeBSD कार्यान्वयन में एक -L विकल्प भी है, डॉक्टर का कहना है कि यह वर्णों की संख्या को सबसे लंबी पंक्ति में लौटाता है, लेकिन मेरा परीक्षण यह इंगित करता है कि इसके बजाय कई बाइट्स हैं (किसी भी प्रदर्शन में प्रदर्शन चौड़ाई नहीं)। OS / X में कोई -L नहीं है, भले ही मुझे उम्मीद है कि यह FreeBSD से प्राप्त होगा।
स्टीफन चेज़लस

यह tabअच्छी तरह से संभालने के लिए लगता है ( माना जाता है कि टैब हर 8 कॉलम को रोकता है)।
स्टीफन चेज़लस 15

वास्तव में, एक से अधिक-लाइन स्ट्रिंग्स के लिए, मैं कहूंगा कि यह वही है जो मैं देख रहा हूं, क्योंकि यह एलएफ नियंत्रण वर्णों को ठीक से संभालता है
स्टीफन चेज़लस

@ स्टीफनचेज़ेलस: क्या अब भी आपको यह समस्या है कि यह पात्रों की संख्या के बजाय बाइट्स की संख्या लौटाता है? मैंने इसे आपके डेटा पर परीक्षण किया और आप जो परिणाम चाहते थे उसे प्राप्त करें: wc -L <<< 'unix'→ 8,  wc -L <<< 'Stéphane'→ 8, और  wc -L <<< 'もで 諤奯ゞ'→ 11. PS आप "स्टीफन" को नौ अक्षर मानते हैं, जिनमें से एक शून्य-चौड़ाई है? यह मुझे आठ पात्रों की तरह लगता है, जिनमें से एक मल्टी बाइट है।
जी-मैन का कहना है 'मोनिका'

@ जी-मैन, मैं FreeBSD कार्यान्वयन का उल्लेख कर रहा था, जो कि FreeBSD 12.0 और UTF-8 लोकेल में अभी भी बाइट्स गिन रहा है। ध्यान दें कि é को एक U + 00E9 वर्ण या U + 0065 (e) वर्ण का उपयोग करके लिखा जा सकता है, इसके बाद U + 0301 (तीव्र उच्चारण का संयोजन), जिसे बाद में प्रश्न में दिखाया गया है।
स्टीफन चेज़लस

4

मेरी .profile, मैं एक स्क्रिप्ट को टर्मिनल पर एक स्ट्रिंग की चौड़ाई निर्धारित करने के लिए कहता हूं। मैं एक मशीन के कंसोल पर लॉग इन करते समय इसका उपयोग करता हूं जहां मैं सिस्टम-सेट पर भरोसा नहीं करता हूं LC_CTYPE, या जब मैं दूरस्थ रूप से लॉग इन करता हूं और LC_CTYPEरिमोट साइड से मिलान करने के लिए भरोसा नहीं कर सकता । मेरी स्क्रिप्ट किसी भी लाइब्रेरी को कॉल करने के बजाय टर्मिनल पर सवाल करती है, क्योंकि यह मेरे उपयोग के मामले में पूरे बिंदु था: टर्मिनल की एन्कोडिंग निर्धारित करें।

यह कई मायनों में नाजुक है:

  • यह प्रदर्शन को संशोधित करता है, इसलिए यह बहुत अच्छा उपयोगकर्ता अनुभव नहीं है;
  • यदि कोई अन्य प्रोग्राम गलत समय पर कुछ प्रदर्शित करता है तो एक दौड़ की स्थिति है;
  • यदि टर्मिनल जवाब नहीं देता है तो यह लॉक हो जाता है। (कुछ साल पहले मैंने पूछा था कि इस पर कैसे सुधार किया जा सकता है , लेकिन यह व्यवहार में बहुत अधिक समस्या नहीं है, इसलिए मुझे उस समाधान पर स्विच करने के लिए कभी भी नहीं मिला। केवल एक मामले में मुझे एक टर्मिनल का सामना करना पड़ा जो जवाब नहीं देता था। एक विंडोज मशीन के साथ एक लिनक्स मशीन से दूरस्थ फ़ाइलों तक पहुँचने के लिए एक इमैक plink, और मैंने इसके बजाय विधि का उपयोग करकेplinkx इसे हल किया ।)

यह आपके उपयोग के मामले से मेल खाता है या नहीं।

#! /bin/sh

if [ z"$ZSH_VERSION" = z ]; then :; else
  emulate sh 2>/dev/null
fi
set -e

help_and_exit () {
  cat <<EOF
Usage: $0 {-NUMBER|TEXT}
Find out the width of TEXT on the terminal.

LIMITATION: this program has been designed to work in an xterm. Only
xterm and sufficiently compatible terminals will work. If you think
this program may be blocked waiting for input from the the terminal,
try entering the characters "0n0n" (digit 0, lowercase letter n,
repeat).

Display TEXT and erase it. Find out the position of the cursor before
and after displaying TEXT so as to compute the width of TEXT. The width
is returned as the exit code of the program. A value of 100 is returned if
the text is wider than 100 columns.

TEXT may contain backslash-escapes: \\0DDD represents the byte whose numeric
value is DDD in octal. Use '\\\\' to include a single backslash character.

You may use -NUMBER instead of TEXT (if TEXT begins with a dash, use
"-- TEXT"). This selects one of the built-in texts that are designed
to discriminate between common encodings. The following table lists
supported values of NUMBER (leftmost column) and the widths of the
sample text in several encodings.

  1  ASCII=0 UTF-8=2 latinN=3 8bits=4
EOF
  exit
}

builtin_text () {
  case $1 in
    -*[!0-9]*)
      echo 1>&2 "$0: bad number: $1"
      exit 119;;
    -1) # UTF8: {\'E\'e}; latin1: {\~A\~A\copyright}; ASCII: {}
      text='\0303\0211\0303\0251';;
    *)
      echo 1>&2 "$0: there is no text number $1. Stop."
      exit 118;;
  esac
}

text=
if [ $# -eq 0 ]; then
  help_and_exit 1>&2
fi
case "$1" in
  --) shift;;
  -h|--help) help_and_exit;;
  -[0-9]) builtin_text "$1";;
  -*)
    echo 1>&2 "$0: unknown option: $1"
    exit 119
esac
if [ z"$text" = z ]; then
  text="$1"
fi

printf "" # test that it is there (abort on very old systems)

csi='\033['
dsr_cpr="${csi}6n" # Device Status Report --- Report Cursor Position
dsr_ok="${csi}5n" # Device Status Report --- Status Report

stty_save=`stty -g`
if [ z"$stty_save" = z ]; then
  echo 1>&2 "$0: \`stty -g' failed ($?)."
  exit 3
fi
initial_x=
final_x=
delta_x=

cleanup () {
  set +e
  # Restore terminal settings
  stty "$stty_save"
  # Restore cursor position (unless something unexpected happened)
  if [ z"$2" = z ]; then
    if [ z"$initial_report" = z ]; then :; else
      x=`expr "${initial_report}" : "\\(.*\\)0"`
      printf "%b" "${csi}${x}H"
    fi
  fi
  if [ z"$1" = z ]; then
    # cleanup was called explicitly, so don't exit.
    # We use `trap : 0' rather than `trap - 0' because the latter doesn't
    # work in older Bourne shells.
    trap : 0
    return
  fi
  exit $1
}
trap 'cleanup 120 no' 0
trap 'cleanup 129' 1
trap 'cleanup 130' 2
trap 'cleanup 131' 3
trap 'cleanup 143' 15

stty eol 0 eof n -echo
printf "%b" "$dsr_cpr$dsr_ok"
initial_report=`tr -dc \;0123456789`
# Get the initial cursor position. Time out if the terminal does not reply
# within 1 second. The trick of calling tr and sleep in a pipeline to put
# them in a process group, and using "kill 0" to kill the whole process
# group, was suggested by Stephane Gimenez at
# /unix/10698/timing-out-in-a-shell-script
#trap : 14
#set +e
#initial_report=`sh -c 'ps -t $(tty) -o pid,ppid,pgid,command >/tmp/p;
#                       { tr -dc \;0123456789 >&3; kill -14 0; } |
#                       { sleep 1; kill -14 0; }' 3>&1`
#set -e
#initial_report=`{ sleep 1; kill 0; } |
#                { tr -dc \;0123456789 </dev/tty; kill 0; }`
if [ z"$initial_report" = z"" ]; then
  # We couldn't read the initial cursor position, so abort.
  cleanup 120
fi
# Write some text and get the final cursor position.
printf "%b%b" "$text" "$dsr_cpr$dsr_ok"
final_report=`tr -dc \;0123456789`

initial_x=`expr "$initial_report" : "[0-9][0-9]*;\\([0-9][0-9]*\\)0" || test $? -eq 1`
final_x=`expr "$final_report" : "[0-9][0-9]*;\\([0-9][0-9]*\\)0" || test $? -eq 1`
delta_x=`expr "$final_x" - "$initial_x" || test $? -eq 1`

cleanup
# Zsh has function-local EXIT traps, even in sh emulation mode. This
# is a long-standing bug.
trap : 0

if [ $delta_x -gt 100 ]; then
  delta_x=100
fi
exit $delta_x

स्क्रिप्ट अपनी वापसी की स्थिति में चौड़ाई लौटाता है, 100 तक चढ़ जाता है। नमूना उपयोग:

widthof -1
case $? in
  0) export LC_CTYPE=C;; # 7-bit charset
  2) locale_search .utf8 .UTF-8;; # utf8
  3) locale_search .iso88591 .ISO8859-1 .latin1 '';; # 8-bit with nonprintable 128-159, we assume latin1
  4) locale_search .iso88591 .ISO8859-1 .latin1 '';; # some full 8-bit charset, we assume latin1
  *) export LC_CTYPE=C;; # weird charset
esac

यह मेरे लिए उपयोगी था (हालाँकि मैंने ज्यादातर आपके गाढ़े संस्करण का उपयोग किया था )। मैं जोड़कर इसके उपयोग एक छोटे से खूबसूरत बना printf "\r%*s\r" $((${#text}+8)) " ";के अंत तक cleanup(8 जोड़ने मनमाना है, यह काफी लंबे समय से बड़े स्थानों के व्यापक उत्पादन को कवर किया है, लेकिन एक लाइन चादर से बचने के लिए पर्याप्त संकीर्ण करने के लिए होने की जरूरत है)। यह परीक्षण को अदृश्य बनाता है, हालांकि यह भी मानता है कि कुछ भी लाइन पर मुद्रित नहीं किया गया है (जो ठीक है ~/.profile)
एडम काटज़

वास्तव में, यह थोड़े से प्रयोग से प्रतीत होता है कि zsh (5.7.1) में आप बस कर सकते हैं text="Éé"और फिर ${#text}आपको डिस्प्ले की चौड़ाई देंगे (मैं 4एक गैर-यूनिकोड टर्मिनल में और 2एक यूनिकोड-अनुरूप टर्मिनल में)। यह बैश के लिए सच नहीं है।
एडम काटज़

@AdamKatz ${#text}आपको डिस्प्ले की चौड़ाई नहीं देता है। यह आपको वर्तमान लोकेल द्वारा उपयोग किए गए एन्कोडिंग में वर्णों की संख्या देता है। जो मेरे उद्देश्य के लिए बेकार है क्योंकि मैं टर्मिनल की एन्कोडिंग का निर्धारण करना चाहता हूं। यदि आप किसी अन्य कारण से प्रदर्शन चौड़ाई चाहते हैं, तो यह उपयोगी है, लेकिन यह सटीक नहीं है क्योंकि प्रत्येक वर्ण एक इकाई चौड़ा नहीं है। उदाहरण के लिए संयोजन के उच्चारण की चौड़ाई 0 है, और चीनी विचारधाराओं की चौड़ाई 2 है
गिल्स एसओ- बुराई को रोकना '

हाँ, अच्छी बात है। यह स्टीफन के प्रश्न को संतुष्ट कर सकता है, लेकिन आपके मूल इरादे को नहीं (जो वास्तव में मैं भी यही करना चाहता था, इस प्रकार मेरा कोड स्वीकार कर रहा हूं)। उम्मीद है मेरी पहली टिप्पणी आपके लिए उपयोगी थी, गिलेज़।
एडम काटज़

3

एरिक प्रुइट ने wcwidth()और wcwidth.awkwcswidth() पर उपलब्ध Awk में एक प्रभावशाली कार्यान्वयन लिखा । यह मुख्य रूप से 4 कार्य प्रदान करता है

wcscolumns(), wcstruncate(), wcwidth(), wcswidth()

जहां wcscolumns()गैर-मुद्रण योग्य वर्ण भी सहन करता है।

$ cat wcscolumns.awk 
{ printf "%d\n", wcscolumns($0) }
$ awk -f wcwidth.awk -f wcscolumns.awk <<< 'unix'
8
$ awk -f wcwidth.awk -f wcscolumns.awk <<< 'Stéphane'
8
$ awk -f wcwidth.awk -f wcscolumns.awk <<< 'もで 諤奯ゞ'
11
$ awk -f wcwidth.awk -f wcscolumns.awk <<< $'My sign is\t鼠鼠'
14

मैंने एक मुद्दा खोला, जिसमें TAB से निपटने के बारे में पूछा गया था जो wcscolumns($'My sign is\t鼠鼠')14. से अधिक होना चाहिए। अपडेट: एरिक ने wcsexpand()TABs को रिक्त स्थान तक विस्तारित करने के लिए फ़ंक्शन को जोड़ा :

$ cat >wcsexpand.awk 
{ printf "%d\n", wcscolumns( wcsexpand($0, 8) ) }
$ awk -f wcwidth.awk -f wcsexpand.awk <<< $'My sign is\t鼠鼠'
20
$ echo $'鼠\tone\n鼠鼠\ttwo'
      one
鼠鼠    two
$ awk -f wcwidth.awk -f wcsexpand.awk <<< $'鼠\tone\n鼠鼠\ttwo'
11
11

1

का उपयोग करते हुए संभावित समाधानों पर संकेत पर विस्तार करने के लिए colऔर ksh93मेरे सवाल में:

डेबियन पर colसे उपयोग करना bsdmainutils(अन्य colकार्यान्वयन के साथ काम नहीं कर सकता है ), एक एकल गैर-नियंत्रण चरित्र की चौड़ाई प्राप्त करने के लिए:

charwidth() {
  set "$(printf '...%s\b\b...\n' "$1" | col -b)"
  echo "$((${#1} - 4))"
}

उदाहरण:

$ charwidth x
1
$ charwidth $'\u301'
0
$ charwidth $'\u94f6'
2

एक स्ट्रिंग के लिए विस्तारित:

stringwidth() {
   awk '
     BEGIN{
       s = ARGV[1]
       l = length(s)
       for (i=0; i<l; i++) {
         s1 = s1 ".."
         s2 = s2 "\b\b"
       }
       print s1 s s2 s1
       exit
     }' "$1" | col -b | awk '
        {print length - 2 * length(ARGV[2]); exit}' - "$1"
}

का उपयोग करते हुए ksh93's printf '%Ls':

charwidth() {
  set "$(printf '.%2Ls.' "$1")"
  echo "$((5 - ${#1}))"
}

stringwidth() {
  set "$(printf '.%*Ls.' "$((2*${#1}))" "$1")" "$1"
  echo "$((2 + 3 * ${#2} - ${#1}))"
}

का उपयोग करते हुए perl's Text::CharWidth:

stringwidth() {
  perl -MText::CharWidth=mbswidth -le 'print mbswidth shift' "$@"
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.