একটি ভাল পেস্ট কমান্ড


11

আমার কাছে নিম্নলিখিত দুটি ফাইল রয়েছে (আমি বিন্দুগুলির সাথে লাইনগুলি প্যাড করেছি যাতে কোনও ফাইলের প্রতিটি লাইন একই প্রস্থ হয় এবং আরও স্পষ্ট করতে ফাইল 1 সমস্ত ক্যাপ তৈরি করে)।

contents of file1:

ETIAM......
SED........
MAECENAS...
DONEC......
SUSPENDISSE

contents of file2

Lorem....
Proin....
Nunc.....
Quisque..
Aenean...
Nam......
Vivamus..
Curabitur
Nullam...

লক্ষ্য করুন যে ফাইল 2 ফাইল 1 এর চেয়ে লম্বা।

আমি যখন এই আদেশটি চালাচ্ছি:

paste file1 file2

আমি এই আউটপুট পেতে

ETIAM...... Lorem....
SED........ Proin....
MAECENAS... Nunc.....
DONEC...... Quisque..
SUSPENDISSE Aenean...
    Nam......
    Vivamus..
    Curabitur
    Nullam...

নিম্নলিখিত হিসাবে আউটপুট জন্য আমি কি করতে পারি?

ETIAM...... Lorem....
SED........ Proin....
MAECENAS... Nunc.....
DONEC...... Quisque..
SUSPENDISSE Aenean...
            Nam......
            Vivamus..
            Curabitur
            Nullam...

আমি চেষ্টা করেছিলাম

paste file1 file2 | column -t

তবে এটি এটি করে:

ETIAM......  Lorem....
SED........  Proin....
MAECENAS...  Nunc.....
DONEC......  Quisque..
SUSPENDISSE  Aenean...
Nam......
Vivamus..
Curabitur
Nullam...

মূল আউটপুট হিসাবে কুৎসিত নয় তবে যাইহোক ভুল কলাম-ভিত্তিক।


2
pasteদ্বিতীয় ফাইল থেকে লাইনগুলির সামনে ট্যাব ব্যবহার করা হচ্ছে। কলামগুলি যথাযথভাবে সারিবদ্ধ করতে আপনাকে পোস্ট প্রসেসর ব্যবহার করতে হতে পারে।
আনচান্ট

3
paste file1 file2 | column -tn?
নিনজালজ

ফাইল 1 এ সবসময় স্থির আকারের কলাম থাকে?
আরএসফালকন

@ আরএসফালকন 7 হ্যাঁ, এটি হয়।
তুলাইনস কর্ডোভা

উত্তর:


17

ধরে নিলাম আপনার ফাইলগুলিতে কোনও ট্যাব অক্ষর নেই,

paste file1 file2 | expand -t 13

-tফাইল 1-এ পছন্দসই সর্বাধিক লাইনের প্রস্থকে কভার করার জন্য উপযুক্তভাবে বেছে নেওয়া হয়েছে।

ওপি আরও নমনীয় সমাধান যুক্ত করেছে:

আমি এটি করেছি তাই এটি 13 নম্বর যাদু ছাড়াই কাজ করে:

paste file1 file2 | expand -t $(( $(wc -L <file1) + 2 ))

এটি টাইপ করা সহজ নয় তবে এটি কোনও স্ক্রিপ্টে ব্যবহার করা যেতে পারে।


চমৎকার! আপনার উত্তরটি পড়ার আগে আমি প্রসারণ সম্পর্কে জানতাম না :)
TabeaKischka

4

আমি ভেবেছিলাম অ্যাজক এটি সুন্দরভাবে করতে পারে, তাই আমি "দুটি ফাইল থেকে বুদ্ধিমান পঠন ইনপুট" গগল করেছিলাম এবং একটি সূচনা পয়েন্ট হিসাবে ব্যবহার করার জন্য স্ট্যাকওভারফ্লোতে একটি নিবন্ধ পেয়েছি ।

প্রথমটি কনডেন্সড সংস্করণ, তারপরে সম্পূর্ণরূপে মন্তব্য করা। এটি কার্যকর হতে কয়েক মিনিটেরও বেশি সময় নিয়েছে। আমি স্মার্ট লোকের কাছ থেকে কিছু সংশোধন করে খুশি হব।

awk '{if(length($0)>max)max=length($0)}
FNR==NR{s1[FNR]=$0;next}{s2[FNR]=$0}
END { format = "%-" max "s\t%-" max "s\n";
  numlines=(NR-FNR)>FNR?NR-FNR:FNR;
  for (i=1; i<=numlines; i++) { printf format, s1[i]?s1[i]:"", s2[i]?s2[i]:"" }
}' file1 file2

এবং এখানে উপরের সম্পূর্ণ ডকুমেন্টেড সংস্করণ রয়েছে।

# 2013-11-05 mike@diehn.net
# Invoke thus:
#   awk -f this_file file1 file2
# The result is what you asked for and the columns will be
# determined by input file order.
#----------------------------------------------------------
# No matter which file we're reading,
# keep track of max line length for use
# in the printf format.
#
{ if ( length($0) > max ) max=length($0) }

# FNR is record number in current file
# NR is record number over all
# while they are equal, we're reading the first file
#   and we load the strings into array "s1"
#   and then go to the "next" line in the file we're reading.
FNR==NR { s1[FNR]=$0; next }

# and when they aren't, we're reading the
#   second file and we put the strings into
#   array s2
{s2[FNR]=$0}

# At the end, after all lines from both files have
# been read,
END {
  # use the max line length to create a printf format
  # the right widths
  format = "%-" max "s\t%-" max "s\n"
  # and figure the number of array elements we need
  # to cycle through in a for loop.
  numlines=(NR-FNR)>FNR?NR-FNR:FNR;
  for (i=1; i<=numlines; i++) {
     printf format, s1[i]?s1[i]:"", s2[i]?s2[i]:""
  }
}

1
+1 এটিই একমাত্র উত্তর যা স্বেচ্ছাসেবিত ইনপুট (যেমন ট্যাবগুলিতে থাকতে পারে এমন লাইনের সাথে) দিয়ে কাজ করে। আমি মনে করি না এটি উল্লেখযোগ্যভাবে পরিশোধিত / উন্নত করা যেতে পারে।
don_crissti

2

খুব ভাল সমাধান নয় তবে আমি এটি ব্যবহার করে সক্ষম হয়েছি

paste file1 file2 | sed 's/^TAB/&&/'

যেখানে ট্যাব অক্ষরের সাথে প্রতিস্থাপন করা হবে।


&&সেড কমান্ডের ভূমিকা কী ?
coffeMug

1
একটি একক &যা অনুসন্ধান করা হচ্ছে তা রাখে (এই ক্ষেত্রে একটি ট্যাব)। এই কমান্ডটি প্রথমে দুটি ট্যাব দিয়ে শুরুতে ট্যাবটি প্রতিস্থাপন করে।
আনটনাট

উবুন্টু ডিবিয়ানের উপর zsh এ এই কাজটি করতে আমাকে পরিবর্তন TABকরতে \tহয়েছিল। এবং এটি কেবল তখনই কাজ করে যদি ফাইল 1 এর 15 টিরও কম অক্ষর থাকে
Rubo77

2

ডেবিয়ান এবং ডেরিভেটিভগুলিতে, columnএকটি -n নোমারেজ বিকল্প রয়েছে যা কলামটি খালি ক্ষেত্রের সাথে সঠিক জিনিসটি করতে দেয়। অভ্যন্তরীণভাবে, ফাংশনটি columnব্যবহার করে wcstok(wcs, delim, ptr), যা delimআর্গুমেন্টের প্রশস্ত অক্ষর দ্বারা বিসর্জনিত টোকেনগুলিতে বিস্তৃত অক্ষরের স্ট্রিংকে বিভক্ত করে ।

wcstokdelimটোকেন সনাক্ত করার আগে, প্রশস্ত অক্ষরগুলি এড়িয়ে শুরু করে starts -nবিকল্প কোন algorythm যে প্রাথমিক ওয়াইড-অক্ষর থামিয়া না ব্যবহার delim

দুর্ভাগ্যক্রমে, এটি খুব বহনযোগ্য নয়: -nএটি দেবিয়ান-নির্দিষ্ট, এবং columnপসিক্সে নয়, এটি সম্ভবত একটি বিএসডি জিনিস।


2

প্যাডিংয়ের জন্য আপনি যে বিন্দুগুলি ব্যবহার করেছেন তা বের করে নিচ্ছেন:

file1:

ETIAM
SED
MAECENAS
DONEC
SUSPENDISSE

file2:

Lorem
Proin
Nunc
Quisque
Aenean
Nam
Vivamus
Curabitur
Nullam

এটা চেষ্টা কর:

$ ( echo ".TS"; echo "l l."; paste file1 file2; echo ".TE" ) | tbl | nroff | more

এবং আপনি পাবেন:

ETIAM         Lorem
SED           Proin
MAECENAS      Nunc
DONEC         Quisque
SUSPENDISSE   Aenean
              Nam
              Vivamus
              Curabitur
              Nullam

এটি, অন্যান্য সমাধানগুলি ব্যবহার করে যেমন pasteট্যাবযুক্ত কোনও লাইন থাকলে সঠিক আউটপুট প্রিন্ট করতে ব্যর্থ হবে। যদিও আলাদা হওয়ার জন্য +1
ডোন_ক্রিস্তি

+1 টি। আপনি কি দয়া করে সমাধানটি কীভাবে ব্যাখ্যা করবেন?
তুলিনস কর্ডোভা

1

এমন একটি awkসমাধান যা মোটামুটি পোর্টেবল হতে হবে এবং একটি নির্বিচার সংখ্যক ইনপুট ফাইলের জন্য কাজ করা উচিত:

# Invoke thus:
#   awk -F\\t -f this_file file1 file2

# every time we read a new file, FNR goes to 1

FNR==1 {
    curfile++                       # current file
}

# read all files and save all the info we'll need
{
    column[curfile,FNR]=$0          # save current line
    nlines[curfile]++               # number of lines in current file
    if (length > len[curfile])
            len[curfile] = length   # max line length in current file
}

# finally, show the lines from all files side by side, as a table
END {
    # iterate through lines until there are no more lines in any file
    for (line = 1; !end; line++) {
            $0 = _
            end = 1

            # iterate through all files, we cannot use
            #   for (file in nlines) because arrays are unordered
            for (file=1; file <= curfile; file++) {
                    # columnate corresponding line from each file
                    $0 = $0 sprintf("%*s" FS, len[file], column[file,line])
                    # at least some file had a corresponding line
                    if (nlines[file] >= line)
                            end = 0
            }

            # don't print a trailing empty line
            if (!end)
                    print
    }
}

আপনি এটি ফাইল 1 এবং ফাইল 2 এ কীভাবে ব্যবহার করবেন? আমি স্ক্রিপ্ট কল করেছি paste-awkএবং চেষ্টা করেছি paste file1 file2|paste-awkএবং চেষ্টা করেছি awk paste-awk file1 file2কিন্তু কোনওটিই কাজ করেনি।
rubo77

আমি পেয়েছিawk: Line:1: (FILENAME=file1 FNR=1) Fatal: Division by zero
rubo77

@ রুবো :77: awk -f paste-awk file1 file2কমপক্ষে জিএনইউ অ্যাওক এবং মক এর জন্য কাজ করা উচিত।
নিনজালজ

এটি কাজ করে, যদিও এটি pasteদুটি সারিগুলির মধ্যে কম স্থানের চেয়ে কিছুটা আলাদা । এবং যদি ইনপুট ফাইলের মধ্যে সমস্ত সারি একই দৈর্ঘ্য না থাকে, তবে এটি একটি ডান সারিবদ্ধ-ডান সারিতে পরিণত হবে
রুবো 77

@ রুবো 77।: ক্ষেত্র বিভাজকটি সেট করা যাবে-F\\t
নিনজালজ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.