कमांड आउटपुट द्वारा फ़ाइल के पहले कॉलम को बदलें


5

इस प्रश्न से यूनिक्स का उपयोग करके कॉलम को कॉपी और बदलें

मैंने एक समाधान बनाने की कोशिश की है जो केवल इस फ़ाइल से काम करता है:

20070101 10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6
20070102 10.2317  79.1638   5.6  26.5  20.8   1.9  13.6  98.0
20070103 10.2317  79.1638   7.5  27.7  20.8   0.1  15.8  96.4
20070104 10.2317  79.1638   8.1  26.0  19.6   0.0  15.5  94.1

और उत्पादन प्राप्त करें:

01/01/2007  10.2317   79.1638   6.0  26.7  20.9   0.8  14.0  98.6
02/01/2007  10.2317   79.1638   5.6  26.5  20.8   1.9  13.6  98.0
03/01/2007  10.2317   79.1638   7.5  27.7  20.8   0.1  15.8  96.4
04/01/2007  10.2317   79.1638   8.1  26.0  19.6   0.0  15.5  94.1

अन्य फ़ाइलों को शामिल किए बिना।

इसलिए मैं पहले कॉलम को परिवर्तित तिथि तक स्थानापन्न करना चाहता हूं।

मुझे मूल फ़ाइल से दिनांक मिली:

$ awk '{print $1}' filedate.txt
20070101
20070102
20070103
20070104

फिर मैंने तारीख रूपांतरण के साथ किया:

for i in $(awk '{print $1}' filedate.txt); do date -d "$i"  +%d/%m/%Y; done
01/01/2007
02/01/2007
03/01/2007
04/01/2007

लेकिन मैं पहले से परिवर्तित दिनांक मानों द्वारा फ़ाइल के पहले कॉलम को संशोधित करने में सक्षम नहीं हूं। मैंने awk प्रतिस्थापन के साथ प्रयास किया ( awk '{$1=$dt}1'):

for i in $(awk '{print $1}' filedate.txt); do dt=$(date -d "$i" +%d/%m/%Y) && awk '{$1=$dt}1' filedate.txt; done

लेकिन जैसा कि एक लूप शामिल है, आउटपुट वांछित नहीं है।

मैं इसे कैसे प्राप्त कर सकता हूं awk? क्या ऐसा करना संभव है sed?

संपादित करें

अन्य प्रश्न की टिप्पणियों में मैंने निम्नलिखित तरीके से देखा sed

 sed 's,^\([0-9]\{4\}\)\([0-9]\{2\}\)\([0-9]\{2\}\),\3/\2/\1,'

लेकिन मैं अब उत्सुक हूँ कि इसे dateकमांड में कैसे शामिल किया जाए ।

जवाबों:


2

आइए अपने पहले से मौजूद लूप का उपयोग करें (जो मैंने वास्तव में नहीं देखा है लेकिन जो अपना काम करता है):

for i in $(awk '{print $1}' filedate.txt); do date -d "$i"  +%d/%m/%Y; done

और फिर उस छोटे से संशोधन के साथ उस पर मेरे दूसरे प्रश्न का उत्तर दें :

for i in $(awk '{print $1}' filedate.txt); do date -d "$i"  +%d/%m/%Y; done |
paste - <( cut -d ' ' -f 2- filedate.txt )

नतीजा:

01/01/2007      10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6
02/01/2007      10.2317  79.1638   5.6  26.5  20.8   1.9  13.6  98.0
03/01/2007      10.2317  79.1638   7.5  27.7  20.8   0.1  15.8  96.4
04/01/2007      10.2317  79.1638   8.1  26.0  19.6   0.0  15.5  94.1

लूप के बिना, छोटा:

date -f <( cut -d ' ' -f 1 filedate.txt ) +"%d/%m/%Y" |
paste - <( cut -d ' ' -f 2- filedate.txt )

पाइप के बिना:

paste <( date -f <( cut -d ' ' -f 1 filedate.txt ) +"%d/%m/%Y" ) \
      <( cut -d ' ' -f 2- filedate.txt )

इन सभी उदाहरणों में स्पष्ट रूप से bashया तो kshया किसी अन्य शेल की आवश्यकता होती है जो प्रक्रिया प्रतिस्थापन को समझता है। जीएनयू dateकी भी आवश्यकता है।

यह कैसे काम करता है की व्याख्या के लिए उस अन्य प्रश्न के लिए मेरा जवाब देखें ।


2

यदि आप जो परिवर्तन चाहते हैं, वह मौजूदा जानकारी का केवल एक पुनरावृत्ति है, तो क्यों नहीं

awk '{ $1=sprintf("%02i/%02i/%04i",
     substr($1, 7, 2), substr($1, 5, 2), substr($1, 1, 4)) }1' file

हम पहले क्षेत्र से सबस्ट्रिंग उठा रहे हैं और उन्हें पहले क्षेत्र के लिए नए मूल्य में फिर से जोड़ रहे हैं, फिर पूरे इनपुट लाइन को सामान्य रूप से प्रिंट कर रहे हैं। ( 1समापन ब्रेस के बाद अकेला बिना शर्त मुद्रण के लिए एक मानक Awk मुहावरा है।)

आप शायद पूरी तरह से अच्छी मशीन-पठनीय तारीखों को बहुत जल्द ही "मानव पठनीय" में परिवर्तित करने पर पछताएंगे


2

यदि आपके पास GNU awk ( gawk) है तो आप कमांड / आउटपुट / फ़ंक्शन के getlineलिए पाइप के रूप का उपयोग करके कमांड आउटपुट का उपयोग करके एक कॉलम को बदल सकते हैं date:

gawk '{"date +%d/%m/%Y -d" $1 | getline $1} 1' file

हालाँकि, यदि आप किसी कॉलम का दिनांक प्रारूप बदलना चाहते हैं, तो आप आंतरिक mktimeऔर strftimeफ़ंक्शंस का उपयोग करके ऐसा कर सकते हैं :

gawk '{
  d = sprintf("%d %02d %02d 0 0 0", substr($1,1,4), substr($1,5,2), substr($1,7,2));
  t = mktime(d);
  $1 = strftime("%d/%m/%Y", t);
  } 1' file

हालांकि इस मामले में आप सरल स्ट्रिंग हेरफेर (जो किसी भी स्वाद में काम करना चाहिए awk) का उपयोग करके आवश्यक रूपांतरण कर सकते हैं :

$ mawk '{$1 = sprintf("%02d/%02d/%02d", substr($1,7,2), substr($1,5,2), substr($1,1,4))} 1' file
01/01/2007 10.2317 79.1638 6.0 26.7 20.9 0.8 14.0 98.6
02/01/2007 10.2317 79.1638 5.6 26.5 20.8 1.9 13.6 98.0
03/01/2007 10.2317 79.1638 7.5 27.7 20.8 0.1 15.8 96.4
04/01/2007 10.2317 79.1638 8.1 26.0 19.6 0.0 15.5 94.1


2

GNU सेड के कमांड के eवैल मॉडिफायर से sआप dateआवश्यकतानुसार तिथियों को परिवर्तित करने के लिए उपयोग कर सकेंगे :

sed -r 's|(\S+)(.*)|date -d \1 "+%d/%m/%y \2"|e'

प्रतिस्थापित अभिव्यक्ति एक अच्छी तरह से बनाई गई तिथि कमांड है। eसंशोधक इस प्रत्येक पंक्ति और पैटर्न बफर (और इस प्रकार उत्पादन) प्रत्येक तिथि आदेश के उत्पादन के साथ प्रतिस्थापित किया के लिए निष्पादित करने के लिए कारण बनता है।


1

हालांकि यह सबसे अच्छा अभ्यास नहीं लग सकता है, मैं एक अलग समाधान के लिए जाऊँगा, जैसे बैश मापदंडों का उपयोग करना।

gv@debi64:$ a="20070101"; b="${a: -2:2}/${a: -4:2}/${a: 0:4}";echo $b
01/01/2007

मैं तब फ़ाइल पढ़ सकता था और कुछ का उपयोग कर sed -i "s/$a/$b/g"सकता था जैसे कि मुझे आपकी आवश्यकता हो सकती है:

gv@debi64:$ cat a.txt
20070101 10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6
20070102 10.2317  79.1638   5.6  26.5  20.8   1.9  13.6  98.0
20070103 10.2317  79.1638   7.5  27.7  20.8   0.1  15.8  96.4
20070104 10.2317  79.1638   8.1  26.0  19.6   0.0  15.5  94.1

gv@debi64:$ while IFS=" " read -r df rest;do ndf="${df: -2:2}/${df: -4:2}/${df: 0:4} "; sed -i "s#$df#$ndf#g" a.txt;done <a.txt

gv@debi64:$ cat a.txt
01/01/2007  10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6
02/01/2007  10.2317  79.1638   5.6  26.5  20.8   1.9  13.6  98.0
03/01/2007  10.2317  79.1638   7.5  27.7  20.8   0.1  15.8  96.4
04/01/2007  10.2317  79.1638   8.1  26.0  19.6   0.0  15.5  94.1
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.