2

I have several plain text tables (table.txt), with time series going from 2005 until 2099. Unfortunately some of them are missing the last day of the time series 31.12.2099, as follow:

YEAR MONTH DAY RES
2005 1     1   1000
2005 1     2   1001
[...]
2099 12    29  1002
2099 12    30  1003

How can I add the missing day of the time series (31.12.2099) by pasting the value (RES) of the previous day? Considering the minimal example provided, the output should look like that:

YEAR MONTH DAY RES
2005 1     1   1000
2005 1     2   1001
[...]
2099 12    29  1002
2099 12    30  1003
2099 12    31  1003
8
  • This is a task with many sub-tasks. Which of these sub-tasks is causing you problems? Oct 23 '15 at 10:29
  • Are you permitted to use awk or perl? Oct 23 '15 at 10:31
  • @StigHemmer - The first problematic task is to find which table missed the 31.12.2099. Afterward I think I am able to paste the value of the previous day.
    – steve
    Oct 23 '15 at 10:33
  • @MarkPlotnick - Definitely permitted to use them!
    – steve
    Oct 23 '15 at 10:34
  • How are the columns delimited? A single tab? Multiple spaces? Oct 23 '15 at 10:38
3

With awk:

awk '{a=$0}1; END{$0=a; if($1==2099&&$2==12&&$3==30){$3=31;print}}' file | column -t
  • r=$0 set the a variable to the whole line.
  • 1 a true condition that all line are printed
  • END{...} that block is executed when all lines are processed
    • $1==2099&&$2==12&&$3==30 if the last line was december 30th, 2099 (the 13th is missing)
    • $3=31 set the day to 31
    • print and print that additional line.
  • column -t is to columnate the list.

The result with your input file:

YEAR  MONTH  DAY  RES
2005  1      1    1000
2005  1      2    1001
...
2099  12     29   1002
2099  12     30   1003
2099  12     31   1003
0
1

The script adds to all table files which have 30 in the last line followed by 2 space and 4 symbols RES the new line with 2099 12 31 RES(from line before):

sed -i '$ s/30\(  ....\)$/&\n2099 12    31\1/' table*
1

Assuming your file names all start with table (if they don't, just change the glob pattern to something that matches all of them), you can do:

for file in table*; do
    awk -vi="2099 12    31" '1;END{if($0!=i){print i,$NF}}' "$file" > "$file".new
done

The awk command defines the variable i to be the missing line. The 1; just prints every line and the END{} block is executed once the entire file has been read. When inside the END{} block, $0 will be the last line read, the last line of the file. If that is not equal to the value of i, print i and the last field (NF) of the last line of the file.

1
  • @Costas d'oh! Of course, very good point. Thanks and fixed.
    – terdon
    Oct 23 '15 at 12:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.