অন্য ফর্ম্যাটের সাথে কোনও ফাইলের যুগে টাইমস্ট্যাম্পগুলি কীভাবে প্রতিস্থাপন করবেন?


10

আমার কাছে এমন একটি ফাইল রয়েছে যা যুগে যুগে তারিখগুলি ধারণ করে যা মানুষের পাঠযোগ্য read তারিখ রূপান্তর কীভাবে করতে হবে তা আমি ইতিমধ্যে জানি, যেমন:

[server01 ~]$ date -d@1472200700
Fri 26 Aug 09:38:20 BST 2016

.. তবে আমি কীভাবে sedফাইলের মধ্যে দিয়ে যেতে পারি এবং সমস্ত এন্ট্রি রূপান্তর করতে পারি তা জানার জন্য আমি লড়াই করছি । ফাইল ফর্ম্যাটটি দেখতে এমন দেখাচ্ছে:

#1472047795
ll /data/holding/email
#1472047906
cat /etc/rsyslog.conf
#1472048038
ll /data/holding/web

1
ভবিষ্যতের রেফারেন্সের জন্য (ধরে নেওয়া এটি একটি বাশ ইতিহাসের ফাইল; এটির মতো দেখতে), HISTTIMEFORMATলেখার সময় ফর্ম্যাটটি নিয়ন্ত্রণ করতে শেল ভেরিয়েবলটি দেখুন ।
টবি স্পিড

@ টবি হিস্টটাইমফর্ম্যাট মানটি প্রদর্শন করার সময় ব্যবহৃত হয় (স্টাটআউট করার সময়), তবে হিস্টফিলটি লেখার সময় কেবল তার স্থিতি (এমনকি অকার্যকর কিছুতে সেট করাও) গুরুত্বপূর্ণ।
dave_thompson_085

ধন্যবাদ @ ডেভ, আমি জানতাম না (নিজে ইতিহাসের ব্যবহারকারী হয়ে উঠছেন না)।
টবির গতি

date -dসোলারিস বলতে পঠনযোগ্য নয় ... আমি ধরে নিচ্ছি এটি বেশিরভাগ জিএনইউ সরঞ্জাম সহ এমন একটি সিস্টেমে রয়েছে? (জিএনইউ এডাব্লুকে / পার্ল তারিখ রূপান্তরগুলি মোকাবেলা করার জন্য আরও বহনযোগ্য পদ্ধতি হতে পারে)। gawk '{ if ($0 ~ /^#[0-9]*$/) {print strftime("%c",substr($0,2)); } else {print} }' < file( strftimeঅ-বহনযোগ্য বলে মনে হচ্ছে ...)
গার্ট ভ্যান ডান বার্গ

উত্তর:


6

ধারাবাহিক ফাইল ফর্ম্যাট ধরে ধরে, bashআপনি লাইন দ্বারা ফাইল লাইন পড়তে পারেন, এটি প্রদত্ত বিন্যাসে পরীক্ষা করে এবং তারপরে রূপান্তরটি করুন:

while IFS= read -r i; do [[ $i =~ ^#([0-9]{10})$ ]] && \
      date -d@"${BASH_REMATCH[1]}"; done <file.txt

BASH_REMATCHএমন একটি অ্যারে যার প্রথম উপাদানটি রেগেক্সের মিলের মধ্যে প্রথম দখল করা গোষ্ঠী =~, এক্ষেত্রে মহাকাব্য।


আপনি যদি ফাইল কাঠামো রাখতে চান:

while IFS= read -r i; do if [[ $i =~ ^#([0-9]{10})$ ]]; then printf '#%s\n' \
   "$(date -d@"${BASH_REMATCH[1]}")"; else printf '%s\n' "$i"; fi; done <file.txt

এটি পরিবর্তিত বিষয়বস্তুগুলিকে STDOUT এ আউটপুট দেবে, এটি কোনও ফাইলে সংরক্ষণ করতে যেমন out.txt:

while ...; do ...; done >out.txt

এখন আপনি যদি চান, আপনি মূল ফাইলটি প্রতিস্থাপন করতে পারেন:

mv out.txt file.txt

উদাহরণ:

$ cat file.txt
#1472047795
ll /data/holding/email
#1472047906
cat /etc/rsyslog.conf
#1472048038
ll /data/holding/web

$ while IFS= read -r i; do [[ $i =~ ^#([0-9]{10})$ ]] && date -d@"${BASH_REMATCH[1]}"; done <file.txt
Wed Aug 24 20:09:55 BDT 2016
Wed Aug 24 20:11:46 BDT 2016
Wed Aug 24 20:13:58 BDT 2016

$ while IFS= read -r i; do if [[ $i =~ ^#([0-9]{10})$ ]]; then printf '#%s\n' "$(date -d@"${BASH_REMATCH[1]}")"; else printf '%s\n' "$i"; fi; done <file.txt
#Wed Aug 24 20:09:55 BDT 2016
ll /data/holding/email
#Wed Aug 24 20:11:46 BDT 2016
cat /etc/rsyslog.conf
#Wed Aug 24 20:13:58 BDT 2016
ll /data/holding/web

ভাল .... যা স্ক্রিনে রূপান্তরিত তারিখটি মুদ্রণ করে, এখন আমি কীভাবে সেই আদেশটি ফাইলটিতে প্রবেশ করতে পারি?
মেশিনেস্ট

@ ম্যাচিনিস্ট আমার সম্পাদনাগুলি পরীক্ষা করে দেখুন ..
হিমাইল

1
আপনার একটি সাম্প্রতিক সংস্করণ ব্যবহার করেন তাহলে bash, printfরূপান্তর নিজেই করতে পারেন: printf '#%(%F %H)T\n' "${BASH_REMATCH[1]}"
চিপনার

14

যদিও জিএনইউ sedদিয়ে এটি সম্ভব যেমন:

sed -E 's/^#([0-9]+).*$/date -d @\1/e'

এটি মারাত্মকভাবে অক্ষম হবে (এবং নির্বিচারে কমান্ড ইনজেকশন দুর্বলতাগুলি প্রবর্তন করা সহজ 1 ) যার অর্থ dateপ্রতিটি #xxxxলাইনের জন্য একটি শেল এবং একটি কমান্ড চালানো হবে , শেল while readলুপের মতো কার্যত খারাপ । এখানে, এর মতো জিনিসগুলি ব্যবহার করা ভাল হবে perlবা gawkএটি হ'ল পাঠ্য প্রক্রিয়াজাতকরণ ইউটিলিটিগুলির মধ্যে অন্তর্নির্মিত তারিখ রূপান্তর ক্ষমতা রয়েছে:

perl  -MPOSIX -pe 's/^#(\d+).*/ctime $1/se'

বা:

gawk '/^#/{$0 = strftime("%c", substr($0, 2))};1'

1 যদি আমরা এর ^#([0-9]).*পরিবর্তে লিখতাম ^#([0-9]).*$(যেমন আমি এই উত্তরটির পূর্ববর্তী সংস্করণে করেছি), তবে ইউটিএফ -8 টির মতো একাধিক বাইট লোকেলগুলিতে (আজকাল প্রচলিত আদর্শ) যেমন একটি ইনপুট সহ #1472047795<0x80>;rebootযেখানে <0x80>এটি বাইট মান 0x80 যেখানে একটি বৈধ অক্ষর গঠন করে না, সেই sকমান্ডটি date -d@1472047795<0x80>; rebootউদাহরণস্বরূপ চলমান শেষ হত । অতিরিক্ত থাকাকালীন $, সেই লাইনগুলি প্রতিস্থাপন করা হবে না। একটি বিকল্প পন্থা হবে s/^#([0-9])/date -d @\1 #/e:, এটি #xxxশেল মন্তব্য হিসাবে তারিখের পরে অংশ ছেড়ে


1
একটি স্ট্রিম وار পদ্ধতিতে সমস্ত রূপান্তর করতে কেবলমাত্র একটি উদাহরণdate -f ব্যবহার করার বিষয়ে কী ?
ডিজিটাল ট্রমা

পার্ল কমান্ডটি সিটিএম $ 1 এর পরে একটি নতুন লাইন যুক্ত করছে বলে মনে হচ্ছে এবং আমি এটি সরানোর কোনও উপায় খুঁজে পাচ্ছি না।
অ্যালেক্স হার্ভে

1
@Alex। ঠিক। সম্পাদনা দেখুন। sপতাকা যুক্ত করা যাতে .*ইনপুটটিতে নতুন লাইনও অন্তর্ভুক্ত করে। আপনি ব্যবহার করতে পারেন strftime "%c", localtime $1
স্টাফেন চেজেলাস

@ স্টাফেনচাজেলাস অনেক ধন্যবাদ thanks এটি একটি দুর্দান্ত উত্তর।
অ্যালেক্স হার্ভে

3

অন্য সমস্ত উত্তর dateপ্রতিটি রূপের তারিখের জন্য একটি নতুন প্রক্রিয়া তৈরি করে যা রূপান্তরিত হওয়া দরকার। আপনার ইনপুট বড় হলে এটি সম্ভাব্যভাবে ওভারহেডের কার্য সম্পাদন করতে পারে।

তবে জিএনইউ তারিখের একটি সহজ -fবিকল্প রয়েছে যা dateএকটি নতুন প্রক্রিয়াটির উদাহরণ হিসাবে একটি নতুন কাঁটাচামচ ছাড়াই ক্রমাগত ইনপুট তারিখগুলি পড়তে দেয়। সুতরাং আমরা ব্যবহার করতে পারেন sed, pasteএবং dateএই পদ্ধতিতে প্রতিটি এক শুধুমাত্র এক বার (2x জন্য উত্পন্ন হওয়া পরার যেমন যে sed) কত বড় ইনপুট নির্বিশেষে:

$ paste -d '\n' <( sed '2~2d;y/#/@/' epoch.txt | date -f - ) <( sed '1~2d' epoch.txt )
Wed Aug 24 07:09:55 PDT 2016
ll /data/holding/email
Wed Aug 24 07:11:46 PDT 2016
cat /etc/rsyslog.conf
Wed Aug 24 07:13:58 PDT 2016
ll /data/holding/web
$ 
  • দুটি sedকমান্ড যথাক্রমে ইনপুটটির সমান এবং বিজোড় লাইনগুলি মুছুন; প্রথমটি সঠিক যুগের টাইমস্ট্যাম্প ফর্ম্যাটটি #দিয়ে প্রতিস্থাপন @করে।
  • প্রথম sedআউটপুটটি তারপরে পাইপ করা হয় date -fযার দ্বারা প্রাপ্ত প্রতিটি ইনপুটটির জন্য প্রয়োজনীয় তারিখ রূপান্তর করে।
  • এই দুটি স্ট্রিমগুলি পরে একক প্রয়োজনীয় আউটপুটটিতে ইন্টারলেস করা হবে paste<( )নির্মান হয় ব্যাশ প্রক্রিয়া বদল যে কার্যকরভাবে চিন্তা এটি দেওয়া ফাইলের নামের থেকে পড়া যখন এটা আসলে পড়া আউটপুট কমান্ড ভিতর থেকে পাইপ রয়েছে পেস্ট কৌতুক। একটি নতুন লাইনের সাথে বিজোড় এবং এমনকি আউটপুট লাইন পৃথক করতে -d '\n'বলে paste। আপনি এটি পরিবর্তন করতে (বা অপসারণ) করতে পারেন যদি উদাহরণস্বরূপ আপনি অন্যান্য পাঠ্যের মতো একই লাইনে টাইমস্ট্যাম্প চান।

নোট করুন যে এই কমান্ডে বেশ কয়েকটি জিএনইউজম এবং বাশিজম রয়েছে। এটি পিক্সিক-কমপ্লায়েন্ট নয় এবং এটি জিএনইউ / লিনাক্স বিশ্বের বাইরে বহনযোগ্য বলে আশা করা উচিত নয়। উদাহরণস্বরূপ date -fওএসএক্স বিএসডি dateভেরিয়েন্টে অন্য কিছু করে ।


date -d(প্রশ্ন থেকে) বহনযোগ্যও নয় ... (ফ্রিবিএসডি তে এটি ডিএসটি সেটিংসের সাথে ঝামেলা করার চেষ্টা করবে, সোলারিসে এটি একটি ত্রুটি দেবে ...) প্রশ্নটি যদিও কোনও ওএস নির্দিষ্ট করে না ...
গার্ট ভ্যান ড্যান বার্গ

@ জার্মটভেনডেনবার্গ হ্যাঁ, এটি এই উত্তরের শেষ অনুচ্ছেদে সম্বোধন করা হয়েছে।
ডিজিটাল ট্রমা

আমি বলতে চাইছি যে প্রশ্নকারীর নমুনাতেও বহনযোগ্য সমস্যা রয়েছে ... (তাদের সম্ভবত কোনও ওএস ট্যাগ করা উচিত ...)
গার্ট ভ্যান ডান বার্গ

1

আপনার পোষ্টটিতে আপনার তারিখের ফর্ম্যাটটি ধরে নেওয়া উচিত যা আপনি চান, নিম্নলিখিত রেজেক্সটি আপনার প্রয়োজনের সাথে খাপ খায়।

sed -E 's/\#(1[0-9]{9})(.*)/echo \1 $(date -d @\1)/e' log.file

এই বিষয়টি প্রতি সচেতন থাকুন এটি প্রতি লাইনে কেবল একটি সময়কে প্রতিস্থাপন করবে।


আমি এই আদেশটি দিয়ে নিম্নলিখিত ত্রুটিটি পাচ্ছি: sed: -e expression #1, char 48: invalid reference \3 on 's' command's RHS
মেশিনবিদ

1
আমার ভুল, পোস্ট সম্পাদনা।
হাটলক

0

সেড ব্যবহার:

sed -r 's/\#([0-9]*)/echo $(date -d @\1)/eg' test.txt

আউটপুট:

ر أغس 24 16:09:55 EET 2016
ll /data/holding/email
ر أغس 24 16:11:46 EET 2016
cat /etc/rsyslog.conf
ر أغس 24 16:13:58 EET 2016
ll /data/holding/web

আমার স্থানীয় ভাষা যেমন আরবি :)


0

পাইপলাইনে কীভাবে করব তা আমার সমাধান solution

cat test.txt | sed 's/^/echo "/; s/\([0-9]\{10\}\)/`date -d @\1`/; s/$/"/' | bash
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.