কীভাবে সংক্ষিপ্ত / পথ / টু / ফাইল থেকে / পি / টি / ফাইল করতে হয়


9

আমি একটি মার্জিত ওয়ান-লাইনার (উদাহরণস্বরূপ awk) সন্ধান করছি যা প্রতিটি প্যারেন্ট / ইন্টারমিডিয়েট স্তরের প্রথম অক্ষর ব্যবহার করে একটি ইউনিক্স পথের একটি স্ট্রিং সংক্ষিপ্ত করে তুলবে, তবে পুরো বেসনামটি। উদাহরণ দ্বারা দেখানো সহজ:

  • /path/to/file/p/t/file
  • /tmp/tmp
  • /foo/bar/.config/wizard_magic/f/b/./wizard_magic
  • /foo/bar/.config/wizard_magic/f/b/.c/wizard_magic
    ভাল পয়েন্ট আলোকে @ MichaelKjörling এবং নীচের @ChrisH দ্বারা, এই উদাহরণ দেখায় কিভাবে আমরা প্রথম দুটি অক্ষর দেখাতে পারেন যখন প্রথম অক্ষর একটি বিন্দু আছে।

একটি পরামর্শ (আমি আপনার ব্যবহারের ক্ষেত্রে জানি না): সংক্ষেপে পরিবর্তে /f/b/.c/wizard_magic। কোনও নির্দিষ্ট ডিরেক্টরিতে বিন্দুটি প্রায়শই সাধারণ হিসাবে দেখা যায় যেদিকে আপনি কোথায় খোঁজ করা উচিত।
ক্রিস এইচ

@ ক্রিসএইচ যা বলেছে তা ছাড়া, .সাধারণত কেবল "বর্তমান ডিরেক্টরি" মানে। সুতরাং /f/b/./wizard_magicহিসাবে একই /f/b/wizard_magicকারণ পাথ উপাদান ./একটি খালি পথ উপাদানে সংকোচন।
একটি সিভিএন

তোমার এতো দরকার কেন? আপনার ইন্টারেক্টিভ শেলটিতে কিছু চালাক স্বতঃপূরণ ব্যবহার করতে পারবেন না (সম্ভবত আপনার শেলটি পর্যাপ্ত কিছুতে পরিবর্তন করা)
বেসিল স্টারিনকিভিচ

উত্তর:


7

এই পরীক্ষার ফাইলের জন্য:

$ cat path
/path/to/file
/tmp
/foo/bar/.config/wizard_magic

সংক্ষেপণগুলি এই অজক কোডটি দিয়ে তৈরি করা যেতে পারে:

$ awk -F/ '{for (i=1;i<NF;i++) $i=substr($i,1,1)} 1' OFS=/ path
/p/t/file
/tmp
/f/b/./wizard_magic

সম্পাদনা 1: ডট-নামের জন্য দুটি অক্ষর ব্যবহার করা

এই সংস্করণটি একটি অক্ষরে ডিরেক্টরি নামগুলি সংক্ষেপ করে যে নামগুলি শুরু হয় .যা দুটি অক্ষরের সাথে সংক্ষেপিত হয়:

$ awk -F/ '{for (i=1;i<NF;i++) $i=substr($i,1,1+($i~/^[.]/))} 1' OFS=/ path
/p/t/file
/tmp
/f/b/.c/wizard_magic

কিভাবে এটা কাজ করে

  • -F/

    এটি ইনপুটটিতে ফিল্ড বিভাজক হিসাবে একটি স্ল্যাশ ব্যবহার করতে ডাবলাকে বলে।

  • for (i=1;i<NF;i++) $i=substr($i,1,1)

    এটি সর্বশেষ ব্যতীত প্রতিটি ক্ষেত্রের উপরে লুপ করে এবং কেবলমাত্র প্রথম অক্ষর দ্বারা এটি প্রতিস্থাপন করে।

    EDIT1: সংশোধিত সংস্করণে ক্ষেত্রটি শুরু হওয়ার সাথে সাথে আমরা স্ট্রিং 2 এর দৈর্ঘ্য তৈরি করি .

  • 1

    এটি সংশোধিত লাইনটি মুদ্রণের জন্য awk কে বলে।

  • OFS=/

    এটি আউটপুটটিতে ফিল্ড বিভাজক হিসাবে একটি স্ল্যাশ ব্যবহার করতে ডাবোধকে বলে।


দুর্দান্ত উত্তর, বিভাজকটি ব্যবহার করার জন্য ছোটখাটো পরিবর্তন : awk -F/ '{for (i=1;i<NF;i++) $i=substr($i,1,1+($i~/^[.]/))(i==1||length($i)<2?"":"‥")} 1' OFS=/ <<<$PWDদেয়: /foo/bar/.config/wizard_magic/f‥/b‥/.c‥/wizard_magic
ধারকর্তা 42

12

বেশ সহজেই সেডে (ধরে নিচ্ছি যে ফাইলের নামগুলিতে কোনও নতুন লাইন নেই):

sed 's!\([^/]\)[^/]*/!\1/!g'

জাঁকজমক কম কম কারণ এটির পিছনে উল্লেখের অভাব রয়েছে (গাওক ব্যতীত, তবে একটি আনাড়ি সিনট্যাক্স সহ):

awk -v FS=/ -v OFS=/ '{for (i=1; i<NF; i++) $i=substr($i,1,1)} 1'

Zsh এ (প্রবেশ পথে $full_path):

echo "${(j:/:)${(@r:1:)${(@s:/:)${full_path:h}}}}/${full_path:t}"

2
আইআইআরসি, "ব্যাকরিফারেন্সস" হ'ল রেফারেন্স স্ট্রিংয়ে নয়, প্যাটার্নগুলিতে ঘটে এমন গ্রুপগুলি ক্যাপচারের জন্য উল্লেখ।
রাইময়েড

@Rhymoid \1প্রতিস্থাপন স্ট্রিং নেই প্যাটার্ন একটি ক্যাপচার গ্রুপ একটি রেফারেন্স মানে। ব্যাকরেফারেন্স হ'ল ব্যাক রেফারেন্স হ'ল আপনি যেখানেই এটি ব্যবহার করেন না কেন।
গিলস 17:59-

8

আপনি এটি যেমন করতে পারেন:

cd /usr///.//share/../share//man/man1 || exit
IFS=/; set -f
printf %.1s/  ${PWD%/*}
printf %s\\n "${PWD##*/}"

/u/s/m/man1

এবং এখানে একটি sed:

printf %s "$file" |
tr /\\n \\n/      | sed -et$ \
    -e '\|^\.\.$|{x;s|\(.*\)\n.*$|\1|;x;}'  \
    -e 's|^\.\{0,2\}$||;\|.|H;$!d;x'        \
-e$ -e '\|\(\.\{0,2\}.\)\(.*\)\(\n\)|!b'    \
    -e 's||\1\3\2\3|;P;s|\n||;D' |
tr /\\n \\n/

এটি নীচে ফাংশনটি করে একই জিনিসগুলির সমস্ত কিছুর কাছে আসে। এটি টিল্ডসের সংক্ষিপ্ত বিবরণ দেয় না বা $PWDশীর্ষস্থানীয় নন-স্ল্যাশের জন্য মাথায় inোকায় না কারণ ফাংশনটি করে (এবং সত্যিকার অর্থে, শীর্ষস্থানীয় স্ল্যাশ কখনই প্রিন্ট করে না) তবে পরে এটি পরিচালনা করা যেতে পারে। এটি নাল পাথ উপাদানগুলি এবং একক-বিন্দুগুলি প্রক্রিয়াজাত করে এবং আগাছা কেটে যায় ..

উপরের manমতো একই পথটি cdপ্রিন্ট করে:

u/s/m/man1

এটি প্রতিটি পথের উপাদানগুলির জন্য এক বা দুটি অতিরিক্ত নেতৃস্থানীয় বিন্দুও মুদ্রণ করবে যা এর সাথে শুরু হয় এবং কেবল এক বা দুটি বিন্দু নয়।

আপনি একটি দিয়ে শুরু করে পথের উপাদানগুলির জন্য এক চরিত্রের চেয়ে বেশি করার বিষয়ে জিজ্ঞাসা করেছিলেন .। এটি করার জন্য আমি প্রতিটি উপাদানকে যেভাবেই ব্যক্তিগত মনোযোগের প্রয়োজন হবে তা বুঝতে পেরেছিলাম এবং যেহেতু আমি কৌতূহলী ছিলাম, আমি পরিবর্তনের ডিরেক্টরিটি ছাড়াই একটি প্রচলিত পথটি বের করার চেষ্টা করেছি tried কিছু ট্রায়াল-এন্ড-ত্রুটির পরে অবশেষে আমি ঠিক করেছি যে এটি করার একমাত্র উপায় এটি দু'বার করা - পিছনের দিকে এবং এগিয়ে:

pathbytes(){
    local IFS=/   o="$-" p
    set -f${ZSH_VERSION+LFy}
    set -- ${1:-$PWD}
    for p   in      /${1:+$PWD} $*
    do      case    $p in   (.|"")  ;;
            (..)    ${1+shift}      ;;
            (/)     set --          ;;
            (*)     set -- $p $*;   esac
    done
    for p   in      //$* ""
    do      case   ${p:-/$3}        in
            ([!./]*)                ;;
            (..*)   set "..$@"      ;;
            (.*)    set ".$@"       ;;
            (//*) ! set "" $1 $1    ;;
            (~)   ! p=\~            ;;
            (~/*)   p="~/$2";set $HOME
                  ! while "${2+shift}" 2>&3
                    do   p="~/${p#??*/}"
                    done 3>/dev/null;;
            esac&&  set ""  "${p%"${p#$1?}"}/$2" "$p/$3"
    done;   printf %s\\n "${p:-$2}"
    set +f  "-${o:--}"
}

যাতে ডিরেক্টরিটি কখনই পরিবর্তন হয় না বা কোনও পাথ উপাদানগুলির অস্তিত্বের নিশ্চয়তা দেওয়ার চেষ্টা করে না, তবে এটি পুনরাবৃত্ত /ডিলিমিটারগুলি নিঃসৃত করে এবং /./সিঙ্গল-ডট উপাদানগুলিকে পুরোপুরি ড্রপ করে এবং /../ডাবল-ডট উপাদানগুলি যথাযথভাবে প্রক্রিয়া করে ।

যখন $IFSকিছু অ-শ্বেতস্পেস অক্ষর সেট করা থাকে , দুই বা ততোধিক $IFSঅক্ষরের অনুক্রমের ফলে এক বা একাধিক নাল ক্ষেত্র দেখা যাবে। সুতরাং একাধিক একটানা স্ল্যাশ নাল-মূল্যবান তর্কগুলিতে কাজ করে। নেতৃস্থানীয় $IFSচরিত্রের ক্ষেত্রেও একই কথা । এবং তাই যখন set -- $1বিভক্ত হয়, ফলাফল $1যদি নাল হয় তবে এটি একটি স্ল্যাশ দিয়ে শুরু হয়েছিল, অন্যথায়, ${1:+$PWD}যদি এটি নাল না হয় তবে আমি inোকান $PWD। অন্য কথায়, যদি প্রথম $PWDতর্কটি স্ল্যাশ দিয়ে শুরু না হয় তবে এটি চাপ দেওয়া হবে । এটি পথের বৈধতার কাছে যতটা কাছাকাছি ।

অন্যথায়, প্রথম forলুপটি পুনরাবৃত্তভাবে পথের উপাদানগুলির ক্রমকে উল্টে দেয়, যেমন:

      1 2 3
1     2 3
2 1   3
3 2 1

... এটি করার সময় এটি কোনও একক ডট বা নাল উপাদান উপেক্ষা করে এবং এর জন্য .....

      1 .. 3
1     .. 3
      3
3

... দ্বিতীয় পাসটি এই প্রভাবটিকে বিপরীত করে, এবং এটি করার সময় এটি প্রতিটি উপাদানকে 2-ডট + চর , বা 1-ডট + চর , বা চরে পরিণত করে

সুতরাং এটি অস্তিত্ব নির্বিশেষে একটি আধ্যাত্মিক পথে কাজ করা উচিত।

আমি দ্বিতীয় লুপটিতে কিছুটা যোগ / বিয়োগ করেছি। এটি এখন setকম প্রায়ই হয় (কেবলমাত্র প্রতিটি [!./]*উপাদানগুলির জন্য একবার ) , এবং শর্ট সার্কিট caseপ্যাটার্ন মূল্যায়নের বেশিরভাগ সময় (উল্লিখিত প্যাটার্নের জন্য ধন্যবাদ) , এবং এর বিপরীতে একটি টেল-কল ম্যাচ-মূল্যায়ন অন্তর্ভুক্ত ~। অবশেষে ক্যানোনিকাল পথের সমস্ত বা একটি শীর্ষস্থানীয় অংশ (পুরো উপাদানগুলিতে বিভক্ত) মিলতে ~পারলে, ম্যাচিং বিটটি কেটে ফেলা হবে এবং একটি আক্ষরিক ~প্রতিস্থাপন করা হবে। এটি করার জন্য, আমাকে সংক্ষিপ্তসারগুলির পাশাপাশি পথের একটি সম্পূর্ণ অনুলিপি বজায় রাখতে হয়েছিল (কারণ সংক্ষিপ্ত পথটির সাথে মিলানো ~সম্ভবত খুব সহায়ক হবে না) , এবং তাই এটি রাখা হয় $3। গতwhileলুপ শাখা কেবল তখনই চালিত হয় যদি এর ~সাবসেট হিসাবে মেলে $3

যদি আপনি এটি set -xট্রেস সক্ষম দ্বারা চালিত করেন তবে আপনি এটি কাজ দেখতে পারেন।

$ (set -x;pathbytes ..abc/def/123///././//.././../.xzy/mno)
+ pathbytes ..abc/def/123///././//.././../.xzy/mno
+ local IFS=/ o=xsmi p
+ set -f
+ set -- ..abc def 123   . .   .. . .. .xzy mno
+ set --
+ set -- home
+ set -- mikeserv home
+ set -- ..abc mikeserv home
+ set -- def ..abc mikeserv home
+ set -- 123 def ..abc mikeserv home
+ shift
+ shift
+ set -- .xzy ..abc mikeserv home
+ set -- mno .xzy ..abc mikeserv home
+ set  mno mno
+ set . mno mno
+ set  .x/mno .xzy/mno
+ set .. .x/mno .xzy/mno
+ set  ..a/.x/mno ..abc/.xzy/mno
+ set  m/..a/.x/mno mikeserv/..abc/.xzy/mno
+ set  h/m/..a/.x/mno home/mikeserv/..abc/.xzy/mno
+ p=~/h/m/..a/.x/mno
+ set  home mikeserv
+ shift
+ p=~/m/..a/.x/mno
+ shift
+ p=~/..a/.x/mno
+
+ printf %s\n ~/..a/.x/mno
~/..a/.x/mno
+ set +f -xsmi

4
শীতল, তবে আমার চোখ ব্যাথা করছে।
গ্লেন জ্যাকম্যান

1
@ ডন_ক্রিসটি - হ্যাঁ!
মাইকজার্ভ

2

ওহ মাই জেড- এর "ফিশি" জেডশ থিমটিতে ইউনিকোড সমর্থন রয়েছে এমনটি করার জন্য একটি পার্ল স্নিপেট রয়েছে:

perl -pe '
   BEGIN {
      binmode STDIN,  ":encoding(UTF-8)";
      binmode STDOUT, ":encoding(UTF-8)";
   }; s|^$HOME|~|g; s|/([^/.])[^/]*(?=/)|/$1|g; s|/\.([^/])[^/]*(?=/)|/.$1|g;
'

1

আপনি কি নিজের সংক্ষিপ্ত নাম রাখতে চান বা এটি আপনার কমান্ডলাইনের জন্য ব্যবহার করতে চান?
কমান্ডলাইনের জন্য আমার নিম্নলিখিত পরামর্শগুলি রয়েছে:
আপনার শেলটি সম্পূর্ণ করার ফাইলটি আপনাকে সহায়তা করে না?
কখনও কখনও আপনি ভাগ্যবান এবং বিশেষ কিছু করতে হবে না:

# /path/to/file -> /p/t/file
ls -l /*/*/file 

# /tmp -> /tmp
cd /tmp

# /foo/bar/.config/wizard_magic -> /f/b/./wizard_magic
ls -l /*/*/*/wizard_magic -> /f/b/./wizard_magic

আপনার যখন আগ্রহী কিছু ডিরেক্টরি কেবল তখনই আপনি ব্যবহার করতে পারেন:

alias cdto="cd /path/to"
alias cdtmp="cd /tmp"
alias cdcfg="cd /foo/bar/.config"
alias cddeep="cd /home/john/workdir/project1/version3/maven/x/y/z/and/more"

অথবা আপনি আপনার প্রিয় ডায়ারের জন্য ভেরিয়েবল সেট আপ করতে পারেন

export p="/path/to"
export f="/foo/bar/.config"
ls -l $p/file
ls -l $f/wizard_magic

আমি মনে করি এই বিকল্পগুলি .bashrc (বা। প্রোফাইল) এর মতো সংজ্ঞায়িত একটি ফাংশন দিয়ে এটি সমাধান করার চেষ্টা করার চেয়ে আরও বেশি অর্থবোধ করে I

function x { 
   xxpath=""
   while [ $# -ne 0 ]; do
     xxpath+="${1}*/"
     shift
   done
   cd $(echo "${xxpath}")
}

এবং এই ফাংশনটি x কে আপনার অক্ষরের মধ্যে ফাঁক দিয়ে বলছে:

 # cd /path/to
 x /p t

 # cd /tmp 
 x /t

 # cd /foo/bar/.config
 x /f b 
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.