সেড কেন একটি ট্যাব হিসাবে স্বীকৃতি দিচ্ছে না?


105
sed "s/\(.*\)/\t\1/" $filename > $sedTmpFile && mv $sedTmpFile $filename

আমি এই sedস্ক্রিপ্টটি tabপ্রতিটি লাইনের সামনে একটি সন্নিবেশ করানোর আশা করছি $filenameতবে তা তা নয়। কিছু কারণে এটি tপরিবর্তে একটি সন্নিবেশ করছে ।


1
যেহেতু সেড প্ল্যাটফর্মগুলির মধ্যে পৃথক হতে পারে (বিশেষত, বিএসডি / ম্যাকোএসএক্স বনাম লিনাক্স), আপনি যে প্ল্যাটফর্মটিতে সেড ব্যবহার করছেন তা নির্দিষ্ট করে দেওয়া সহায়ক হতে পারে।
আইজাক

সেড "এস / (। *) / # \ 1 /" $ ফাইলের নাম | tr '#' '\ t'> $ sedTmpFile &&vv $ sedTmpFile $ ফাইলের নাম।
ব্যবহারকারী 2432405

ওএস এক্স (ম্যাকোস) ব্যবহারকারীর জন্য, এই প্রশ্নটি দেখুন
ফ্র্যাঙ্কলিন ইউ

উত্তর:


129

সমস্ত সংস্করণ sedবোঝার নয় \t। পরিবর্তে কেবল একটি আক্ষরিক ট্যাব (োকান ( তারপরে Ctrl- টিপুন )।VTab


2
অই হ্যাঁ; স্পষ্ট করে \tবলার জন্য: সমস্ত সংস্করণ প্রকাশের প্রতিস্থাপনের অংশে বুঝতে পারে না (এটি \tপ্যাটার্নের সাথে মিলিত অংশে স্বীকৃত )
জন ওয়েলডন

3
awwwwwwwwwwwwwwwwwwwww, ঠিক আছে এটি বেশ আকর্ষণীয়। অদ্ভুত। আপনি এটিকে অন্য জায়গায় নয় কেন এটি একটি জায়গায় চিনিয়ে তুলবেন ...?
ষাট ফুটারসুডে এপাদ

2
স্ক্রিপ্ট থেকে আহ্বান করা হয়েছে, এটি কাজ করবে না: ট্যাবগুলি sh দ্বারা উপেক্ষা করা হবে। উদাহরণস্বরূপ, শেল স্ক্রিপ্ট থেকে নিম্নলিখিত কোডটি কোনও টেবুলেশন দ্বারা প্রিপেন্ড না করে $ TEXT_TO_ADD যুক্ত করবে: "" $ {লাইন} a $ $ TEXT_TO_ADD "$ ফাইল।
ডেরিকসন

2
: - @Dereckson এবং অন্যদের এই উত্তরটি দেখুন stackoverflow.com/a/2623007/48082
Cheeso

2
ডেরিকসন এস / ক্যান / পারবেন না /?
ডগলাস

41

ব্যাশ ব্যবহার করে আপনি প্রোগ্রামের মতো কোনও ট্যাব অক্ষর sertোকাতে পারেন:

TAB=$'\t' 
echo 'line' | sed "s/.*/${TAB}&/g" 
echo 'line' | sed 's/.*/'"${TAB}"'&/g'   # use of Bash string concatenation

এটি খুব সহায়ক।
চিজো

1
আপনি সঠিক ট্র্যাকের সাথে ছিলেন $'string'তবে ব্যাখ্যাটির অভাব রয়েছে। প্রকৃতপক্ষে আমি সন্দেহ করি, অত্যন্ত বিশ্রী ব্যবহারের কারণে আপনার সম্ভবত একটি অসম্পূর্ণ বোঝাপড়া রয়েছে (যেমন আমাদের বেশিরভাগ ব্যাশ দিয়ে থাকে)। : নীচের আমার ব্যাখ্যা দেখুন stackoverflow.com/a/43190120/117471
ব্রুনো Bronosky

1
মনে রাখবেন যে বেস $TABএকক উদ্ধৃতিগুলির মতো ভেরিয়েবলগুলি প্রসারিত করবে না , সুতরাং আপনার এটির দ্বিগুণ উদ্ধৃতি ব্যবহার করা দরকার।
নীলামকবি

*ডাবল কোটসের অভ্যন্তরে ব্যবহার সম্পর্কে সতর্কতা অবলম্বন করুন ... এটিকে গ্লোব হিসাবে বিবেচনা করা হবে, আপনার ইচ্ছাকৃত রেজেক্স হিসাবে নয়।
levigroker

27

@sedit সঠিক পথে ছিল তবে ভেরিয়েবলটি সংজ্ঞায়িত করা কিছুটা বিশ্রী।

সমাধান (বাশ নির্দিষ্ট)

ব্যাশে এটি করার উপায়টি হল আপনার একক উদ্ধৃত স্ট্রিংয়ের সামনে ডলারের সাইন স্থাপন করা।

$ echo -e '1\n2\n3'
1
2
3

$ echo -e '1\n2\n3' | sed 's/.*/\t&/g'
t1
t2
t3

$ echo -e '1\n2\n3' | sed $'s/.*/\t&/g'
    1
    2
    3

যদি আপনার স্ট্রিংয়ে ভেরিয়েবল সম্প্রসারণ অন্তর্ভুক্ত করা দরকার হয় তবে আপনি উদ্ধৃত স্ট্রিংগুলি একসাথে এভাবে রাখতে পারেন:

$ timestamp=$(date +%s)
$ echo -e '1\n2\n3' | sed "s/.*/$timestamp"$'\t&/g'
1491237958  1
1491237958  2
1491237958  3

ব্যাখ্যা

বাশ-এর $'string'কারণে "এএনএসআই-সি সম্প্রসারণ" ঘটে। এবং যে কি আমাদের অধিকাংশ আশা যখন আমরা ভালো জিনিস ব্যবহার করেন \t, \r, \n: ইত্যাদি থেকে https://www.gnu.org/software/bash/manual/html_node/ANSI_002dC-Quoting.html#ANSI_002dC-Quoting

ফর্মের শব্দগুলি 'স্ট্রিং' বিশেষভাবে চিকিত্সা করা হয়। শব্দটি স্ট্রিংয়ে প্রসারিত হয় , এএনএসআই সি স্ট্যান্ডার্ড অনুসারে ব্যাকস্ল্যাশ-পলায়নযুক্ত অক্ষর প্রতিস্থাপন করা হয়েছিল। ব্যাকস্ল্যাশ পালানোর ক্রমগুলি যদি উপস্থিত থাকে তবে ডিকোড করা হয়েছে ...

প্রসারিত ফলাফলটি একক-উদ্ধৃত, যেন ডলারের সাইন উপস্থিত ছিল না।

সমাধান (যদি আপনাকে অবশ্যই বাশ এড়ানো আবশ্যক)

আমি ব্যক্তিগতভাবে মনে করি বাশ এড়ানোর বেশিরভাগ প্রচেষ্টা নিরীহ কারণ বাশিজম এড়ানো আপনার কোডকে * বহনযোগ্য করে তোলে না। (আপনি bash -euযদি বাশ এড়ানো এবং ব্যবহার করার চেষ্টা করেন তবে আপনি যদি কোডটি শেবাং করেন তবে আপনার কোডটি কম ভঙ্গুর হবে sh[যদি আপনি নিখরচায় পসিক্স নিনজা না হন]) তবে এ সম্পর্কে কোনও ধর্মীয় যুক্তি না দিয়ে আমি আপনাকে সেরা দেই * উত্তর.

$ echo -e '1\n2\n3' | sed "s/.*/$(printf '\t')&/g"
    1
    2
    3

* সর্বোত্তম উত্তর? হ্যাঁ, কারণ বেশিরভাগ অ্যান্টি-ব্যাশ শেল স্ক্রিপ্টগুলি তাদের কোডে কী ভুল করবে তার একটি উদাহরণ @ রব্রেকর্ডের উত্তরecho '\t' হিসাবে ব্যবহার করা হয়েছে । এটি জিএনইউ প্রতিধ্বনির জন্য কাজ করবে, তবে বিএসডি প্রতিধ্বনি নয়। এটি ওপেন গ্রুপ দ্বারা http://pubs.opengroup.org/onlinepubs/9699919799/utilities/echo.html#tag_20_37_16 এ ব্যাখ্যা করা হয়েছে এবং বাশিজমগুলি এড়াতে সচরাচর কেন ব্যর্থ হয় তার এটি একটি উদাহরণ।


8

আমি উবুন্টু 12.04 (এলটিএস) এর বাশ শেলের সাথে এরকম কিছু ব্যবহার করেছি:

ট্যাব সহ একটি নতুন লাইন যুক্ত করতে , প্রথম যখন প্রথম মিল হয়:

sed -i '/first/a \\t second' filename

ট্যাব দিয়ে প্রথমে প্রতিস্থাপন করতে , দ্বিতীয় :

sed -i 's/first/\\t second/g' filename

4
ডাবল এস্কেপ কী, অর্থাত্ ব্যবহার \\tএবং না \t
জামনটস

আমাকে উবুন্টু ১.0.০৪ এবং বাশ ৪.৩ এ একক উদ্ধৃতিগুলির পরিবর্তে ডাবল উদ্ধৃতি ব্যবহার করতে হয়েছিল।
কাবা

4

ব্যবহার $(echo '\t')। প্যাটার্নটির চারপাশে আপনার উদ্ধৃতিগুলির প্রয়োজন হবে।

যেমন। একটি ট্যাব অপসারণ করতে:

sed "s/$(echo '\t')//"

5
এটি মজার বিষয় যে আপনি "BSN সেড" নির্দিষ্ট বাগটি সমাধান করার জন্য একটি "জিএনইউ প্রতিধ্বনি" সুনির্দিষ্ট বৈশিষ্ট্যটি (ট্যাব অক্ষর হিসাবে ব্যাখ্যা \ t) ব্যবহার করছেন (2 টি পৃথক অক্ষর হিসাবে pre t কে ব্যাখ্যা করছেন)। সম্ভবত, আপনার যদি "জিএনইউ প্রতিধ্বনি" থাকে তবে আপনার কাছে "জিএনইউ সেড "ও থাকবে। কোন ক্ষেত্রে আপনার প্রতিধ্বনি ব্যবহার করার প্রয়োজন হবে না। BSD প্রতিধ্বনির সাথে echo '\t'2 পৃথক অক্ষর আউটপুট যাচ্ছে। পসিক্স পোর্টেবল উপায়টি হ'ল ব্যবহার করা printf '\t'। এই কারণেই আমি বলছি: ব্যাশ ব্যবহার না করে আপনার কোডকে পোর্টেবল করার চেষ্টা করবেন না। আপনি যা ভাবেন তার চেয়ে কঠিন। bashআমাদের মধ্যে বেশিরভাগই করতে পারা যায় এমনটি ব্যবহার করা।
ব্রুনো ব্রোনোস্কি

3

sedবাস্তবে যখন আপনাকে বাস্তবে ব্যবহার করার দরকার নেই তখন আপনি লাইনের সামনে একটি ট্যাব tabোকাতে চান। কেবলমাত্র এটি মুদ্রণের তুলনায় এই ক্ষেত্রে প্রতিস্থাপন একটি ব্যয়বহুল ক্রিয়াকলাপ, বিশেষত যখন আপনি বড় ফাইলগুলির সাথে কাজ করছেন। এটি রিজেক্স না হিসাবে পড়তেও সহজ।

যেমন awk ব্যবহার

awk '{print "\t"$0}' $filename > temp && mv temp $filename


0

sedসমর্থন করে না \t, বা অন্যান্য পালানোর ক্রমগুলিও \nএই বিষয়টির মতো নয়। এটি করার একমাত্র উপায় হ'ল আসলে স্ক্রিপ্টটি ব্যবহার করে ট্যাব অক্ষরটি সন্নিবেশ করানো sed

এটি বলেছিল, আপনি পার্ল বা পাইথন ব্যবহার বিবেচনা করতে পারেন। আমি এখানে একটি ছোট পাইথন স্ক্রিপ্ট লিখেছি যে আমি সমস্ত স্ট্রিম রিজেক্সিংয়ের জন্য ব্যবহার করি:

#!/usr/bin/env python
import sys
import re

def main(args):
  if len(args) < 2:
    print >> sys.stderr, 'Usage: <search-pattern> <replace-expr>'
    raise SystemExit

  p = re.compile(args[0], re.MULTILINE | re.DOTALL)
  s = sys.stdin.read()
  print p.sub(args[1], s),

if __name__ == '__main__':
  main(sys.argv[1:])

2
এবং পার্ল সংস্করণটি হ'ল শেল ওয়ান-লাইনার "পার্ল -পিপ্স '/ এ / বি /' ফাইলের নাম" বা "কিছু | পার্ল -পি 'এর / এ / বি /'"
ত্রিফিক


0

আমি মনে করি অন্যদের অন্যান্য পন্থা (জন্য পর্যাপ্তরূপে এই ব্যাখ্যা আছে sed, AWKইত্যাদি)। তবে, আমার-নির্দিষ্ট bashউত্তরগুলি (ম্যাকোস হাই সিয়েরা এবং সেন্টোস 6/7 এ পরীক্ষিত) অনুসরণ করে।

1) ওপি যদি তারা মূলত প্রস্তাবিত অনুরূপ অনুসন্ধান-এবং-প্রতিস্থাপন পদ্ধতিটি ব্যবহার করতে চায়, তবে আমি perlনীচের মত এটির জন্য ব্যবহারের পরামর্শ দেব । দ্রষ্টব্য: Regex জন্য প্রথম বন্ধনী আগে ব্যাকস্ল্যাশ প্রয়োজন নেই হওয়া উচিত, এবং এই কোড লাইন প্রতিফলিত কিভাবে $1ছাড়া ব্যবহার করা উত্তম \1সঙ্গে perlপ্রতিকল্পন অপারেটর (যেমন প্রতি পার্ল 5 ডকুমেন্টেশন )।

perl -pe 's/(.*)/\t$1/' $filename > $sedTmpFile && mv $sedTmpFile $filename

২) তবে, ঘোস্টডোগ by৪ দ্বারা চিহ্নিত হিসাবে , যেহেতু কাঙ্ক্ষিত অপারেশনটি আসলে প্রতিটি লাইনটির শুরুতে একটি ট্যাব যুক্ত করে ইনপুট / টার্গেট ফাইল ( $filename) এ টিএমপি ফাইলটি পরিবর্তন করার আগে , আমি perlআবার সুপারিশ করব তবে নীচের পরিবর্তনের সাথে (গুলি):

perl -pe 's/^/\t/' $filename > $sedTmpFile && mv $sedTmpFile $filename
## OR
perl -pe $'s/^/\t/' $filename > $sedTmpFile && mv $sedTmpFile $filename

3) অবশ্যই, টিএমপি ফাইলটি অতিমাত্রায় প্রোথিত , তাই কেবল 'স্থানে' ( -iপতাকা যুক্ত করা) সবকিছু করা এবং জিনিসগুলিকে আরও মার্জিত ওয়ান-লাইনারে সরল করে তোলা ভাল with

perl -i -pe $'s/^/\t/' $filename
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.