কিভাবে আগের লাইনে লাইন যুক্ত করা যায়?


9

আমার কাছে একটি লগ ফাইল রয়েছে যা পার্স এবং বিশ্লেষণ করা দরকার। ফাইলটিতে নীচের মতো কিছু রয়েছে:

ফাইল:

20141101 server contain dump
20141101 server contain nothing
    {uekdmsam ikdas 

jwdjamc ksadkek} ssfjddkc * kdlsdl
sddsfd jfkdfk 
20141101 server contain dump

উপরের দৃশ্যের উপর ভিত্তি করে, আমাকে পরীক্ষা করতে হবে যে প্রারম্ভের লাইনে তারিখ বা নম্বরটি আমার পূর্ববর্তী লাইনে সংযুক্ত করতে হবে না।

আউটপুট ফাইল:

20141101 server contain dump
20141101 server contain nothing {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdl sddsfd jfkdfk 
20141101 server contain dump

উত্তর:


11

perlনেতিবাচক লুক হেডস ব্যবহার করে একটি সংস্করণ :

$ perl -0pe 's/\n(?!([0-9]{8}|$))//g' test.txt
20141101 server contain dump
20141101 server contain nothing    {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdlsddsfd jfkdfk
20141101 server contain dump

-0পুরো ফাইল জুড়ে রেজেক্সের সাথে মিলে যাওয়ার অনুমতি দেয় এবং \n(?!([0-9]{8}|$))এটি একটি নেতিবাচক চেহারা, যার অর্থ একটি নিউলাইন 8 টি সংখ্যা দ্বারা অনুসরণ করা হয় না, বা রেখার শেষ (যা দিয়ে -0, ফাইলটি শেষ হবে)।


@terdon, সর্বশেষ নিউলাইন সংরক্ষণ করতে আপডেট হয়েছে।
মুড়ু

সুন্দর! আমি আপনাকে উজ্জীবিত করতে চাই তবে আমি ভয় পেয়েছি যে আমি ইতিমধ্যে পেয়েছি :)
টেরডন

না, -0যদি NUL- সীমাবদ্ধ রেকর্ডের জন্য থাকে। -0777সম্পূর্ণ ফাইলটিকে স্মৃতিতে স্লাপ করতে ব্যবহার করুন (যা আপনার এখানে দরকার নেই)।
স্টাফেন চেজেলাস

@ স্টাফেনচেজেলস তাই পুরো ফাইলটি পড়া ছাড়াও পার্লকে নতুন লাইনের সাথে ম্যাচ করার সেরা উপায় কী?
মুড়ু

অন্যান্য উত্তরগুলি দেখুন যা লাইন দ্বারা ফাইল লাইন প্রক্রিয়া করে।
স্টাফেন চেজেলাস

5

এর সাথে কিছুটা সহজ হতে পারে sed

sed -e ':1 ; N ; $!b1' -e 's/\n\+\( *[^0-9]\)/\1/g'
  • প্রথম অংশটি 1 লম্বা লাইনে :1;N;$!b1বিভক্ত ফাইলের সমস্ত লাইন সংগ্রহ করুন\n

  • দ্বিতীয় অংশটি স্ট্র্যাপ করুন নিউলাইন প্রতীক যদি এটির মধ্যে সম্ভাব্য জায়গাগুলি সহ অ-অঙ্ক চিহ্নটি অনুসরণ করে।

স্মৃতি সীমাবদ্ধতা এড়াতে (বড় ফাইলগুলির জন্য বিশেষত) আপনি ব্যবহার করতে পারেন:

sed -e '1{h;d}' -e '1!{/^[0-9]/!{H;d};/^[0-9]/x;$G}' -e 's/\n\+\( *[^0-9]\)/\1/g'

অথবা একটি জটিল sedস্ক্রিপ্টগুলি ভুলে যান এবং সেই বছরটি শুরু থেকে মনে রাখবেন2

tr '\n2' ' \n' | sed -e '1!s/^/2/' -e 1{/^$/d} -e $a

ভাল, +1। এটি কীভাবে কাজ করে তার ব্যাখ্যা আপনি যুক্ত করতে পারেন?
terdon

1
হুম। খুশী হলাম। আমি সবসময় নিজেকে tr '\n' $'\a' | sed $'s/\a\a*\( *[^0-9]\)/\1/g' | tr $'\a' '\n'করি।
মীরাবিলো

দুঃখিত, সেড (1) এ প্যাসিক বেসিক নিয়মিত এক্সপ্রেসন এস নয় এমন জিনিসগুলি ব্যবহার করার জন্য আপনাকে ডাউনওয়েট করতে হবে , এটি জিএনইউজম।
মীরাবিলো

1
@ কোস্টাস, এটি জিএনইউ গ্রেপের ম্যান পেজ। পসিক্স বিআরই স্পেক রয়েছে । BRE সমতুল্য ERE +হয় \{1,\}[\n]পোর্টেবল হয় না। \n\{1,\}পসিক্স হবে।
স্টাফেন চেজেলাস

1
এছাড়াও, লেবেলের পরে আপনার আর কোনও কমান্ড থাকতে পারে না। পসিক্স সেডগুলিতে লেবেলটি : 1;xসংজ্ঞায়িত করা 1;x। সুতরাং আপনি প্রয়োজন: sed -e :1 -e 'N;$!b1' -e 's/\n\{1,\}\( *[^0-9]\)/\1/g'। আরও মনে রাখবেন যে অনেকগুলি sedবাস্তবায়নের ক্ষেত্রে তাদের প্যাটার্ন স্পেসের আকারের একটি ছোট সীমা রয়েছে (POSIX কেবলমাত্র 10 x LINE_MAX IIRC এর নিশ্চয়তা দেয়)।
স্টাফেন চেজেলাস

5

একটি উপায় হবে:

 $ perl -lne 's/^/\n/ if $.>1 && /^\d+/; printf "%s",$_' file
 20141101 server contain dump
 20141101 server contain nothing    {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdlsddsfd jfkdfk 
 20141101 server contain dump

তবে .এটি চূড়ান্ত নতুন লাইনটিও সরিয়ে দেয়। এটি আবার যুক্ত করতে, ব্যবহার করুন:

$ { perl -lne 's/^/\n/ if $.>1 && /^\d+/; printf "%s",$_' file; echo; } > new

ব্যাখ্যা

এটি -lট্রেলিং করা নতুনলাইনগুলি সরিয়ে ফেলবে (এবং প্রতিটি printকলটিতে আমি একটি যুক্ত করব যার কারণে আমি এর printfপরিবর্তে ব্যবহার করি , তারপরে, যদি বর্তমান লাইনটি সংখ্যাগুলির সাথে শুরু হয় /^\d+/) ( ) এবং বর্তমান লাইন নম্বরটি একের বেশি হয় ( $.>1, এটি অতিরিক্ত যুক্ত এড়াতে প্রয়োজন শুরুতে খালি লাইন), একটি যোগ \nলাইনের শুরুতে। printfপ্রতিটি লাইনে ছাপে।


বিকল্পভাবে, আপনি সমস্ত \nঅক্ষর এতে পরিবর্তন করতে পারেন \0, তারপরে \0সংখ্যার স্ট্রিংয়ের আগে যেগুলি সঠিক তা \nআবার পরিবর্তন করতে পারেন :

$ tr '\n' '\0' < file | perl -pe 's/\0\d+ |$/\n$&/g' | tr -d '\0'
20141101 server contain dump
20141101 server contain nothing    {uekdmsam ikdas jwdjamc ksadkek} ssfjddkc * kdlsdlsddsfd jfkdfk 
20141101 server contain dump

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

$ tr '\n' '\0' < file | perl -pe 's/\0\d{8} |$/\n$&/g' | tr -d '\0'

প্রথম যুক্তিটি printfহ'ল বিন্যাস । ব্যবহারprintf "%s", $_
স্টাফেন চ্যাজেলাস

@ স্টাফেনচাজেলাস কেন? আমি বলতে চাই, আমি জানি এটি পরিষ্কার এবং সহজেই বুঝতে সহজ তবে এটির কি কোনও বিপদ থেকে রক্ষা পাবে?
টেরডন

হ্যাঁ, এটি ভুল এবং সম্ভাব্য বিপজ্জনক যদি ইনপুটটিতে% টি অক্ষর থাকতে পারে। %10000000000sউদাহরণস্বরূপ একটি ইনপুট দিয়ে চেষ্টা করুন ।
স্টাফেন চেজেলাস

সি তে, এটি একটি খুব সুপরিচিত খুব খারাপ অনুশীলন এবং দুর্বলতার উত্স। সাথে perl, echo %.10000000000f | perl -ne printfআমার মেশিনটিকে তার হাঁটুতে নিয়ে আসে।
স্টাফেন চেজেলাস

@ স্টাফেনচেজেলাস বাহ, হ্যাঁ আমারও. যথেষ্ট যথেষ্ট তারপর, উত্তর সম্পাদিত এবং ধন্যবাদ।
টেরডন

3

ব্যবহার করে এটি করার চেষ্টা করুন :

#!/usr/bin/awk -f

{
    # if the current line begins with 8 digits followed by
    # 'nothing' OR the current line doesn't start with 8 digits
    if (/^[0-9]{8}.*nothing/ || !/^[0-9]{8}/) {
        # print current line without newline
        printf "%s", $0
        # feeding a 'state' variable
        weird=1
    }
    else {
        # if last line was treated in the 'if' statement
        if (weird==1) {
            printf "\n%s", $0
            weird=0
        }
        else {
            print # print the current line
        }
    }
}
END{
    print # add a newline when there's no more line to treat
}

এটি ব্যবহার করতে:

chmod +x script.awk
./script.awk file.txt



0

লে প্রোগ্রাম এন বাশ:

while read LINE
do
    if [[ $LINE =~ ^[0-9]{8} ]]
    then
        echo -ne "\n${LINE} "
    else
        echo -n "${LINE} "
    fi
done < file.txt

এক-লাইন আকারে:

while read L; do if [[ $L =~ ^[0-9]{8} ]]; then echo -ne "\n${L} "; else echo -n "${L} "; fi done < file.txt

ব্যাকস্ল্যাশ সংরক্ষণ ( read -r) এবং শীর্ষস্থানীয় স্থানগুলি (ঠিক এর IFS=পরে while) সহ সমাধান:

while IFS= read -r LINE
do
    if [[ $LINE =~ ^[0-9]{8} ]]
    then
        echo
        echo -nE "\n${LINE} "
    else
        echo -nE "${LINE} "
    fi
done < file.txt

এক-লাইন ফর্ম:

while IFS= read -r L; do if [[ $L =~ ^[0-9]{8} ]]; then echo; echo -nE "${L} "; else echo -nE "${L} "; fi done < file.text

লাইনে যদি একটি ব্যাকস্ল্যাশ এবং একটি থাকে তবে এটি ভেঙে যাবে n। এটি হোয়াইটস্পেসে স্ট্রিপ করে। তবে আপনি এটি করতে ব্যবহার করতে পারেন mksh:while IFS= read -r L; do [[ $L = [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]* ]] && print; print -nr -- "$L"; done; print
মীরাবিলোস

অবশ্যই এটি প্রতিটি অ্যালগরিদমের জন্য নয়, তবে কার্য দ্বারা সরবরাহিত প্রয়োজনীয়তার জন্য সমাধান। অবশ্যই চূড়ান্ত সমাধানটি এক নজরে আরও জটিল এবং কম পঠনযোগ্য হবে কারণ এটি রিয়েল লাইফে সাধারণত ঘটে থাকে :)
রোক

আমি সম্মত, তবে আমি ওপি সম্পর্কে খুব বেশি ধারণা না নেওয়ার কঠিন উপায়টি শিখেছি ☺ বিশেষত যদি তারা প্রকৃত পাঠ্যটি ডামি পাঠ্য দ্বারা প্রতিস্থাপন করে।
মীরাবিলোস

0
[shyam@localhost ~]$ perl -lne 's/^/\n/ if $.>1 && /^\d+/; printf "%s",$_' appendDateText.txt

এটা চলবে

i/p:
##06/12/2016 20:30 Test Test Test
##TestTest
##06/12/2019 20:30 abbs  abcbcb abcbc
##06/11/2016 20:30 test test
##i123312331233123312331233123312331233123312331233Test
## 06/12/2016 20:30 abc

o/p:
##06/12/2016 20:30 Test Test TestTestTest
##06/12/2019 20:30 abbs  abcbcb abcbc
##06/11/2016 20:30 test ##testi123312331233123312331233123312331233123312331233Test
06/12/2016 20:30 abc vi appendDateText.txt 
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.