একটি অক্ষরের স্ট্রিংয়ের প্রস্থের প্রস্থ পান


15

শেল স্ক্রিপ্ট থেকে অক্ষরের একটি স্ট্রিংয়ের ডিসপ্লে প্রস্থ (কমপক্ষে (বর্তমানের লোকালগুলিতে সঠিক প্রস্থের সাথে অক্ষর প্রদর্শন করে এমন একটি)) প্রস্থটি পাওয়ার জন্য পোর্টেবল উপায়টির সবচেয়ে কাছেরটি কী হবে?

আমি প্রাথমিকভাবে নিয়ন্ত্রণবিহীন অক্ষরের প্রস্থে আগ্রহী কিন্তু এমন সমাধানগুলি যা ব্যাকস্পেস, ক্যারেজ রিটার্ন, অনুভূমিক টেবুলেশনগুলির মতো অ্যাকাউন্ট নিয়ন্ত্রণের অক্ষরে গ্রহণ করে welcome

অন্য কথায়, আমি পসিক্স ফাংশনটির চারপাশে একটি শেল এপিআই খুঁজছি 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) চেষ্টা করুন এবং যে আহরণ করা, একটি TEXT এর :: CharWidth perlঅন্তত মডিউল, কিন্তু আরো সরাসরি অথবা পোর্টেবল পন্থা আছে।

এটি অন্যান্য প্রশ্নটির কমবেশি অনুসরণ করে যা স্ক্রিনের ডানদিকে পাঠ্য প্রদর্শন করার বিষয়ে ছিল যার জন্য পাঠ্যটি প্রদর্শন করার আগে আপনার সেই তথ্য থাকা দরকার।


উত্তর:


7

একটি টার্মিনাল এমুলেটরে, কার্সর অবস্থানের প্রতিবেদনটি পজিশনের আগে / পরে পেতে, যেমন, থেকে ব্যবহার করতে পারে

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

এবং টার্মিনালে মুদ্রিত অক্ষরগুলি কতটা সন্ধান করুন। যেহেতু এটি কোনও ইসিএমএ -৮৮ (পাশাপাশি ভিটি 100) নিয়ন্ত্রণ সিকোয়েন্সটি আপনি ব্যবহার করতে পারেন এমন কোনও টার্মিনাল দ্বারা সমর্থিত, এটি মোটামুটি বহনযোগ্য।

রেফারেন্সের জন্য

    সিএসআই পিএস এন ডিভাইস স্থিতি প্রতিবেদন (ডিএসআর)।
              ...
                পিএস = 6 -> কার্সার অবস্থানের প্রতিবেদন (সিপিআর) [সারি; কলাম]।
              ফলাফলটি সিএসআই আর; সি আর

শেষ পর্যন্ত, টার্মিনাল এমুলেটর এই কারণগুলির কারণে মুদ্রণযোগ্য প্রস্থ নির্ধারণ করে:

  • লোকাল সেটিংস যেভাবে স্ট্রিংকে ফর্ম্যাট করা যেতে পারে তার উপর প্রভাব ফেলে তবে টার্মিনালটিতে প্রেরিত বাইটের ধারাবাহিকটি টার্মিনালটি কীভাবে কনফিগার করা হয়েছে তার ভিত্তিতে ব্যাখ্যা করা হয় (লক্ষ্য করা যায় যে কিছু লোক যুক্তি দিবে যে এটি ইউটিএফ -8 হতে হবে, অন্যদিকে প্রশ্নবোধে বৈশিষ্ট্যযুক্ত বহনযোগ্যতা ছিল)।
  • wcswidthঅক্ষরগুলি কীভাবে পরিচালনা করা হয় তা একাই বলে না; পজিক্স এই ফাংশনের বর্ণনায় এই দিকটি উল্লেখ করে না।
  • কিছু অক্ষর (উদাহরণস্বরূপ লাইন অঙ্কন) যা একক-প্রস্থ হিসাবে মঞ্জুর হতে পারে তা হ'ল (ইউনিকোডে) "দ্ব্যর্থহীন প্রস্থ", wcswidthএকা ব্যবহার করে কোনও অ্যাপ্লিকেশনটির বহনযোগ্যতা (উদাহরণস্বরূপ অধ্যায় 2 সাইগউইন সেটআপ করা ) দেখুন। xtermউদাহরণস্বরূপ কনফিগারেশনের জন্য ডাবল-প্রস্থের অক্ষর নির্বাচন করার বিধান রয়েছে provision
  • মুদ্রণযোগ্য অক্ষরগুলি ব্যতীত অন্য কোনও কিছুই হ্যান্ডেল করতে আপনাকে টার্মিনাল এমুলেটরটির উপর নির্ভর করতে হবে (যদি না আপনি এটি অনুকরণ করতে চান)।

শেল এপিআই কলগুলি wcswidthবিভিন্ন ডিগ্রীতে সমর্থিত:

এগুলি কম-বেশি সরাসরি: wcswidthপার্লের ক্ষেত্রে সিমুলেট করা , রুবি এবং পাইথন থেকে সি রানটাইম কল করা। আপনি পাইথন থেকে অভিশাপগুলিও ব্যবহার করতে পারেন (যা অক্ষরের সংমিশ্রণ করবে):

  • সেটআপটার্ম ব্যবহার করে টার্মিনালটি সূচনা করুন (স্ক্রিনে কোনও পাঠ্য লেখা হয় না)
  • filterফাংশনটি ব্যবহার করুন (একক লাইনের জন্য)
  • লাইনের শুরুতে পাঠ্যটি আঁকুন addstrত্রুটির জন্য পরীক্ষা করা (যদি এটি খুব দীর্ঘ হয়) এবং তারপরে শেষের অবস্থানের জন্য
  • যদি ঘর থাকে তবে প্রারম্ভিক অবস্থানটি সামঞ্জস্য করুন।
  • কল endwin(যা একটি করা উচিত নয় refresh)
  • প্রারম্ভিক অবস্থান সম্পর্কে ফলাফল স্ট্যান্ডার্ড আউটপুট লিখুন

আউটপুট জন্য অভিশাপ ব্যবহার (তথ্য কোনও স্ক্রিপ্টে ফিড করা বা সরাসরি কল করার চেয়ে tput) পুরো লাইনটি সাফ করে দেবে ( filterএটি কোনও লাইনে সীমাবদ্ধ করে)।


আমি মনে করি এটি অবশ্যই একমাত্র উপায়, সত্যই। যদি টার্মিনাল ডাবল-প্রস্থের অক্ষরগুলি সমর্থন করে না, তবে কিছুতেই কী wcswidth()বলা উচিত তা বিবেচ্য নয়।
মাইকজার্ভ

অনুশীলনে, এই পদ্ধতির সাথে আমার একমাত্র সমস্যাটি হ'ল এটি কোনও নিয়ন্ত্রণ ক্রমের প্রতিক্রিয়া না জানালেও plinkসেট TERM=xtermকরে। তবে আমি খুব বহিরাগত টার্মিনাল ব্যবহার করি না।
গিলস 'অশুভ হওয়া বন্ধ করুন'

ধন্যবাদ। তবে ধারণাটি ছিল টার্মিনালে স্ট্রিং প্রদর্শন করার আগে সেই তথ্যটি পাওয়া (এটি কোথায় প্রদর্শিত হবে তা জানতে, এটি টার্মিনালের ডানদিকে একটি স্ট্রিং প্রদর্শন সম্পর্কে সাম্প্রতিক প্রশ্নটির একটি ফলো-আপ, সম্ভবত আমার উল্লেখ করা উচিত ছিল যদিও আমার আসল প্রশ্নটি ছিল কীভাবে শেল থেকে ডাব্লুএসসিউইদথে যাব)) @ মাইক্রোসার্ভ, হ্যাঁ ডাব্লুএসসিইউইথ () কোনও নির্দিষ্ট টার্মিনালটি কীভাবে একটি নির্দিষ্ট স্ট্রিং প্রদর্শন করবে সে সম্পর্কে ভুল হতে পারে, তবে এটি আপনি টার্মিনাল-ইন্ডিপেন্ডেন্ট সলিউশনে পৌঁছানোর মতোই কাছাকাছি এবং এটি আমার সিস্টেমে কল / কেএসএস-প্রিন্টফ ব্যবহার করতে পারে।
স্টাফেন চেজেলাস

আমি এটি সম্পর্কে অবহিত, তবে ডাব্লুএসসিউইথটি কম পোর্টেবল বৈশিষ্ট্যগুলি ব্যতীত সরাসরি অ্যাক্সেসযোগ্য নয় (আপনি কিছু অনুমানের মাধ্যমে পার্লে এটি করতে পারতেন - দেখুন Search.cpan.org/dist/Text-CharWidth/CharWidth.pm দেখুন ) । উপায় দ্বারা ডান সারিবদ্ধকরণ প্রশ্নটি সম্ভবত (সম্ভবত) স্ট্রিংটি নীচে-বামে লিখে এবং তারপরে কার্সার-অবস্থান এবং সন্নিবেশ-নিয়ন্ত্রণগুলি ব্যবহার করে এটি নীচে-ডানে স্থানান্তরিত হতে পারে।
থমাস ডিকি

1
@ foldস্টাফেনচেজেলাস - বহুমুখী বর্ধিত এবং প্রসারিত প্রস্থের অক্ষরগুলি পরিচালনা করার জন্য স্পষ্টতই নির্দিষ্ট করা হয়েছে । এটি কীভাবে ব্যাকস্পেস পরিচালনা করবে তা এখানে: লাইনের প্রস্থের বর্তমান গণনা একের মাধ্যমে হ্রাস পাবে, যদিও গণনাটি কখনও নেতিবাচক হয়ে উঠবে না। ভাঁজ ইউটিলিটি কোনও <ব্যাকস্পেস> এর ঠিক আগে বা পরে << নিউলাইন> সন্নিবেশ করতে পারে না, যদি না নিম্নলিখিত অক্ষরটির প্রস্থ 1 এর চেয়ে বেশি হয় এবং রেখার প্রস্থ প্রস্থকে অতিক্রম করতে পারে। সম্ভবত fold -w[num]এবং pr +[num]একরকম আপ করা যেতে পারে?
মাইক্রোসার্ভ

5

এক-লাইনের স্ট্রিংয়ের জন্য, জিএনইউ বাস্তবায়নের wcএকটি -L(ওরফে --max-line-length) বিকল্প রয়েছে যা আপনি যা খুঁজছেন ঠিক তেমনই করে (নিয়ন্ত্রণ চরগুলি ব্যতীত)।


1
ধন্যবাদ। এটি ডিসপ্লে প্রস্থটি ফিরিয়ে দেবে আমার কোনও ধারণা ছিল না। নোট করুন যে ফ্রিবিএসডি বাস্তবায়নেও একটি-এল বিকল্প রয়েছে, ডক বলেছেন যে এটি দীর্ঘতম রেখায় অক্ষরের সংখ্যা প্রদান করে, তবে আমার পরীক্ষাটি মনে হয় এটি পরিবর্তে এটি বাইটের একটি সংখ্যা (কোনও ক্ষেত্রে প্রদর্শন প্রস্থ নয়) not ওএস / এক্স এর কোনও এল-এল নেই যদিও আমি এটি ফ্রিবিএসডি থেকে প্রাপ্ত করার আশা করতাম।
স্টাফেন চেজেলাস

এটি হ্যান্ডেল করার tabজন্যও মনে হয় (ধরে নেয় ট্যাব প্রতি 8 টি কলাম থামবে)।
স্টাফেন চেজেলাস

প্রকৃতপক্ষে, এক-এক-লাইন স্ট্রিংয়ের জন্য, আমি এটি বলব যা আমি যা খুঁজছি ঠিক এটিই করে, যেমন এটি এলএফ নিয়ন্ত্রণের অক্ষরগুলি সঠিকভাবে পরিচালনা করে ।
স্টাফেন চেজেলাস

@ স্টাফেনচেজেলাস: আপনি কি এখনও বিষয়টি নিয়ে রয়েছেন যে এটি অক্ষরের সংখ্যার চেয়ে বাইটের সংখ্যা ফেরত দেয়? আমি এটি আপনার ডেটাতে পরীক্ষা করেছি এবং আপনি যে ফলাফলগুলি চেয়েছিলেন তা পেয়েছি: wc -L <<< 'unix'→ 8,  wc -L <<< 'Stéphane'→ 8, এবং  wc -L <<< 'もで 諤奯ゞ'→ 11. PS পিএস আপনি "স্টাফেন" কে নয়টি চরিত্র হিসাবে বিবেচনা করছেন, যার একটি শূন্য-প্রস্থ? এটি আমার কাছে আটটি চরিত্রের মতো দেখাচ্ছে, যার মধ্যে একটি মাল্টি-বাইট।
জি-ম্যান

@ জি-ম্যান, আমি ফ্রিবিএসডি বাস্তবায়নের কথা উল্লেখ করছিলাম, যা ফ্রিবিএসডি 12.0 এবং একটি ইউটিএফ -8 স্থানীয় স্থানে এখনও বাইটগুলি গণনা করছে। নোট করুন যে one একটি U + 00E9 অক্ষর বা একটি U + 0065 (e) অক্ষর ব্যবহার করে U + 0301 (তীব্র উচ্চারণের সংমিশ্রণ) ব্যবহার করে রচনা করা যেতে পারে, যা পরবর্তীটিতে প্রশ্নটিতে প্রদর্শিত হয়েছিল।
স্টাফেন চেজেলাস

4

আমার মধ্যে .profile, আমি টার্মিনালের স্ট্রিংয়ের প্রস্থ নির্ধারণ করতে একটি স্ক্রিপ্ট কল করি। আমি এমন কোনও মেশিনের কনসোলে লগ ইন করার সময় এটি ব্যবহার করি যেখানে আমি সিস্টেম-সেটে বিশ্বাস করি না LC_CTYPE, বা যখন আমি দূর থেকে লগ ইন করি এবং LC_CTYPEদূরবর্তী দিকটি মেলাতে বিশ্বাস করতে পারি না । আমার স্ক্রিপ্টটি কোনও লাইব্রেরি কল করার পরিবর্তে টার্মিনালটিকে জিজ্ঞাসা করে, কারণ এটি আমার ব্যবহারের ক্ষেত্রে পুরো বিষয়টি ছিল: টার্মিনালের এনকোডিংটি নির্ধারণ করুন।

এটি বিভিন্ন উপায়ে ভঙ্গুর:

  • এটি প্রদর্শনটি পরিবর্তন করে, তাই এটি খুব ভাল ব্যবহারকারীর অভিজ্ঞতা নয়;
  • অন্য প্রোগ্রামটি যদি ভুল সময়ে কিছু প্রদর্শন করে তবে রেসের শর্ত রয়েছে;
  • টার্মিনাল প্রতিক্রিয়া না জানালে এটি লক হয়ে যায়। (কয়েক বছর আগে আমি কীভাবে এটির উন্নতি করতে চেয়েছিলাম , তবে এটি বাস্তবে খুব একটা সমস্যা হয়ে ওঠেনি তাই আমি কখনই সমাধানে স্যুইচিংয়ের কাছাকাছি আসিনি। একমাত্র টার্মিনাল যা আমি প্রতিক্রিয়া জানায় না সেটাই হয়েছিল doesn't একটি উইন্ডোজ ইম্যাকস 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 এ ক্লিপ করা হয়েছে ample নমুনা ব্যবহার:

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একটি ইউনিকোড-কমপ্লায়েন্ট টার্মিনালে পেয়েছি )। এটি বাশের পক্ষে সত্য নয়।
অ্যাডাম কাটজ

@ অ্যাডাম্যাট্যাটজ ${#text}আপনাকে ডিসপ্লের প্রস্থ দেয় না। এটি আপনাকে বর্তমান লোকাল দ্বারা ব্যবহৃত এনকোডিংগুলিতে অক্ষরের সংখ্যা দেয়। যা আমার উদ্দেশ্যটির জন্য অকেজো, যেহেতু আমি টার্মিনালের এনকোডিংটি নির্ধারণ করতে চাই। আপনি যদি অন্য কোনও কারণে ডিসপ্লে প্রস্থ চান তবে এটি কার্যকর, তবে এটি সঠিক নয় কারণ প্রতিটি অক্ষর এক ইউনিট প্রশস্ত নয়। উদাহরণস্বরূপ অ্যাকসেন্টগুলির সংমিশ্রণটির দৈর্ঘ্য 0 হয় এবং চীনা
আদর্শগ্রন্থগুলির

হ্যাঁ, ভাল পয়েন্ট। এটি স্টাফেনের প্রশ্নটিকে সন্তুষ্ট করতে পারে তবে আপনার মূল অভিপ্রায়টি নয় (যা আসলে আমিও করতে চেয়েছিলাম, এইভাবে আপনার কোডটি আমার সাথে খাপ খাইয়ে নিচ্ছে)। আশা করি আমার প্রথম মন্তব্যটি আপনার জন্য সহায়ক ছিল, গিলস।
অ্যাডাম কাটজ

3

এরিক Pruitt এর একটি হৃদয়গ্রাহী বাস্তবায়ন লিখেছিলেন wcwidth()এবং wcswidth()এ উপলব্ধ awk মধ্যে wcwidth.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

আমি 14 বছরের বেশি হওয়া উচিত বলেই ট্যাবগুলি পরিচালনা করার বিষয়ে জিজ্ঞাসা করে একটি সমস্যা খুলেছি Update আপডেট: এরিক টিএবিগুলি স্পেসে প্রসারিত করার জন্য ফাংশনটি যুক্ত করেছেন :wcscolumns($'My sign is\t鼠鼠')wcsexpand()

$ 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' "$@"
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.