I have these lines in a file:
Oct 29 23:14:39
Oct 30 19:45:15
Oct 31 13:15:19
Nov 1 10:34:15
Nov 2 18:39:20
Nov 3 12:34:59
Nov 4 16:34:59
Nov 5 20:34:59
When I run sort -r -k2 it gives me the following:
Nov 5
Nov 4
Nov 3
Oct 31
Oct 30
Oct 29
Nov 2
Nov 1
How do I get it like so:
Nov 5
Nov 4
Nov 3
Nov 2
Nov 1
Oct 31
Oct 30
Oct 29
Would appreciate any pointers, comments, advices at all. Do I also need to sort on months in reverse order? How? -M -r?
Assuming the dates are sorted in the file, just reverse the line order:
tac file
This works well!
sort -k1Mr -r -k2nr file.txt
file.txt content
Oct 6 20:34:59
Oct 29 23:14:39
Oct 30 19:45:15
Oct 31 13:15:19
Nov 1 10:34:15
Nov 2 18:39:20
Nov 3 12:34:59
Nov 4 16:34:59
Nov 5 20:34:59
Output:
Nov 5 20:34:59
Nov 4 16:34:59
Nov 3 12:34:59
Nov 2 18:39:20
Nov 1 10:34:15
Oct 31 13:15:19
Oct 30 19:45:15
Oct 29 23:14:39
Oct 6 20:34:59
NOTE:
The following answers fail to sort the entry Oct 6 20:34:59 if exists.
sort -k1,1 -k2r,2
sort -rM
This works for me:
sort -k1Mr,1 -k2r,2
month-sorted by field #1 reversely, then sorted by field #2 reversely
Nov 5 20:34:59
Nov 4 16:34:59
Nov 3 12:34:59
Nov 2 18:39:20
Nov 1 10:34:15
Oct 31 13:15:19
Oct 30 19:45:15
Oct 29 23:14:39
Edit:
A key specification like -k2 means to take all the fields from 2 to the end of the line into account.
To sort by a single column, use -k2,2 as the key specification. This means to use the fields from #2 to #2, i.e. only the second field.
man sort
-k, --key=KEYDEF
sort via a key; KEYDEF gives location and type
...
KEYDEF is F[.C][OPTS][,F[.C][OPTS]] for start and stop position, where
F is a field number and C a character position in the field; both are
origin 1, and the stop position defaults to the line's end.
The arrangement of the fields is lucky, in that the primary one comes first, and the secondary one second (and the rest of the line doesn't matter because you have at most one entry per day). But your example has only Oct and Nov, and I don't think you ought to rely on that. If you add e.g. Aug 7 you'll need a more robust solution. I suggest:
sort -rM
That is, sort in the default way (by the first field, then by the second), treat any month abbreviation found as a month abbreviation, and reverse the whole thing.
EDIT: This is incorrect. #SaSkY's answer is the correct one.
Related
I have 3 variables, $commonName, $expiryDate and $DaysRemInUnixEpoch. Each variable has 3 lines as below output. I want to display output of all 3 variables in to 3 different columns. I tried looking for solution using printf but no luck. Can anyone please advise if they have done this in the past using printf and how? Any help will be much appreciated.
Below are 3 variables output together in one column. I want to split in to 3 columns having 3 rows in each column.
bash-4.1$ echo -e "$commonName\n$expiryDate\n$daysRemInUnixEpoch"
mycertificate_mycert.mycomp.net
PSIN0P551
ROOTROOTCA
Feb 6 2022 11:57:32 GMT
Jan 9 2023 18:51:25 GMT
Mar 12 2035 18:24:54 GMT
682
1020
5465
bash-4.1$
desired output I am looking for is something like below
mycertificate_mycert.mycomp.net Feb 6 2022 11:57:32 GMT 682
PSIN0P551 Jan 9 2023 18:51:25 GMT 1020
ROOTROOTCA Mar 12 2035 18:24:54 GMT 5465
With bash (Process Substitution), paste and column:
paste -d ';' <(echo "$commonName") <(echo "$expiryDate") <(echo "$daysRemInUnixEpoch") | column -s ';' -t
Output:
mycertificate_mycert.mycomp.net Feb 6 2022 11:57:32 GMT 682
PSIN0P551 Jan 9 2023 18:51:25 GMT 1020
ROOTROOTCA Mar 12 2035 18:24:54 GMT 5465
I assume that your variables do not contain ;.
see: man paste and man column
I have two text files (new.txt and old.txt) which contains the recursively navigated directories.
new.txt
338465485 16 drwxr-x--- 26 encqa2 encqa2 16384 Nov 13 06:04 ./
338465486 4 drwxr-x--- 4 encqa2 encqa2 4096 Sep 19 08:38 ./excalibur
338465487 8 drwxr-x--- 3 encqa2 encqa2 8192 Nov 11 14:33 ./excalibur/data_in
338465488 4 drwxr-x--- 2 encqa2 encqa2 4096 Nov 9 23:16 ./excalibur/data_in/archive
old.txt
338101011 40 drwxr-x--- 26 encqa2 encqa2 36864 Nov 13 06:05 ./
338101012 4 drwxr-x--- 4 encqa2 encqa2 4096 Dec 14 2016 ./manual
338101013 4 drwxr-x--- 2 encqa2 encqa2 4096 Aug 25 2016 ./manual/sorted
338101014 4 drwxr-x--- 2 encqa2 encqa2 4096 Aug 25 2016 ./manual/archive
338101015 4 drwxr-x--- 4 encqa2 encqa2 4096 Aug 25 2016 ./adp
338101016 4 drwxr-x--- 6 encqa2 encqa2 4096 Aug 25 2016 ./adp/0235
what I need is the only it provides me the directories , i.e
expected output after diff should be
./
./excalibur
./excalibur/data_in
./excalibur/data_in/archive
./excalibur/archive
./shares
./shares/data_in
./shares/data_in/archive
./shares/sorted
please provide me the command
If I understand correctly, you want to do get those lines from the two text files which are different, but from these lines you want to output only the directory names, not the full information.
If you do a
diff {old,new}.txt
the differing lines are marked in the output with either a '>' or a '<' in the first column, so you get the desired lines by grepping for these characters:
diff {old,new}.txt | grep '^[<>]' | ....
Now you need only the file names. This is easiest if you know for sure that your pathes won't contain any space. In this case, you can, for instance, pipe your data into:
... | grep -oE ' [^ ]+$' | cut -d ' ' -f 2 | ...
If however the file names can contain spaces, you need to follow a different strategy. For instance, if you know that the number of characters in each line up to the file name is always the same, you can use cut -c .... to select the last portion of the line. Otherwise, you would need to process each line using a regular expression which describes the portion you want to throw away. I would use in this case Perl or Ruby, because I'm most familiar with this, but it can also be done with other tools - Zsh, awk, sed.
After this, you need to remove duplicates. These may occur for instance if a line differs between new.txt and old.txt not in the filename part, but in the file information part. This can be done by finally piping everything into
.... | sort -u
I need to cut something from stream, but it seems, that cut cant process last line before EOL or EOF appear.
My bash command:
tail -n 5 -F /data/apache/log/error/error-log | cut -d ' ' -f1-5
log file contains for example:
[Wed Jan 14 09:00:00 2015] [error] Error 1
[Wed Jan 14 09:10:00 2015] [error] Error 2
[Wed Jan 14 09:20:00 2015] [error] Error 3
[Wed Jan 14 09:30:00 2015] [error] Error 4
[Wed Jan 14 09:40:00 2015] [error] Error 5
but my output is:
[Wed Jan 14 09:00:00 2015]
[Wed Jan 14 09:10:00 2015]
[Wed Jan 14 09:20:00 2015]
[Wed Jan 14 09:30:00 2015]
is there a way to make cut process (and output) last, unfinished line if there are all needed columns (first five) streamed already?
My desired output should contain last line from stream:
[Wed Jan 14 09:00:00 2015]
[Wed Jan 14 09:10:00 2015]
[Wed Jan 14 09:20:00 2015]
[Wed Jan 14 09:30:00 2015]
[Wed Jan 14 09:40:00 2015]
//edit
Answers "remove -F" are useless, because I need it for live stream. Whenever apache add new entry into log, I need immediately process it with cut. Without user interaction, without running script again etc. Just process stream in real time in the way, that 'cut' don't wait for EOL before it process (and output) line.
If that is not possible, fine, I try to find workaround, but please, don't tell me to not use live stream when I need live stream!
Finally, after some tests, I found that the problem is not the tail but the cut. Replacing cut by awk fixes the problem:
tail -n 5 -F /data/apache/log/error/error-log | awk '{print $1, $2, $3, $4, $5}'
Is it really necessary -F (follow & retry) option?
Remove it, and it'll work.
This is text.txt
APR
AUG
DEC
FEB
JAN
JUL
JUN
MAR
MAY
NOV
OCT
SEP
I had try
sort -k1M text.txt
sort -M test.txt
It also can't sort by the month like
Jan
Feb
Mar
bla bla bla...
Any mistake at my command?
thank you
Can reproduce this issue with GNU sort 8.21 and a default time locale different than english, which may be your case.
First, check the current setting for date/time values:
grille#ced10:~$ locale | grep -i time
LC_TIME="it_IT.UTF-8"
In fact mine is not english, so sort -m won't work as expected with english month names:
grille#ced10:~$ cat /tmp/mesi
AUG
JAN
JUL
FEB
grille#ced10:~$ sort -M /tmp/mesi
AUG
JAN
JUL
FEB
The solution is to temporarily alter the LC_TIME value to an english one:
grille#ced10:~$ LC_TIME="en_EN.UTF-8" sort -M /tmp/mesi
JAN
FEB
JUL
AUG
Don't worry about messing up things, because after the execution of the command in which locale variable was altered, its original value is automatically restored:
grille#ced10:~$ locale | grep -i time
LC_TIME="it_IT.UTF-8"
have a nice day
1.Please check invisible (nonprinting) symbols in your text file using e.g.
cat -v your_text_file
or
od -xc your_text_file|head
2.Exclude possible ambiguity by starting "sort --version" and sort of your text file specifying absolute path of sort.
This question already has answers here:
Difference in date time
(3 answers)
Closed 9 years ago.
I have 2 variables.
GMDCOM variable stores the date time in below format
Tue Oct 1 13:37:38 2013
Tue Oct 1 13:32:40 2013
Tue Oct 1 13:37:53 2013
GMDRRS variable stores the date time in the below format
Tue Oct 1 13:35:33 2013
Tue Oct 1 13:34:33 2013
Tue Oct 1 13:32:33 2013
I want to calculate the datetime difference
e.g Tue Oct 1 13:37:38 2013 - Tue Oct 1 13:35:33 2013 in hh:mm:ss format
and store it in another variable. I dont want to use PERL, AWK or SED. Instead i want to use normal BASH Shell commands to achieve it. Please help.
Try following
#!/bin/bash
GMDCOM='Tue Oct 1 13:37:38 2013'
GMDRRS='Tue Oct 1 13:35:33 2013'
d1=$(date -d "$GMDCOM" +%s)
d2=$(date -d "$GMDRRS" +%s)
dd=$(($d1-$d2))
ss=$(($dd%60))
mm=$((($dd/60)%60))
hh=$((($dd/3600)%60))
printf "%02d:%02d:%02d\n" "$hh" "$mm" "$ss"