jq/fromdateiso8601 discrepancy on MacOS/Ubuntu - jq

I run following two commands on both MacOS and Ubuntu :
jq -n '"1971-08-01T01:00:00Z" | fromdateiso8601'
jq -n '"1972-08-01T01:00:00Z" | fromdateiso8601'
On MacOS, they give 49856400 and 81482400.
On Ubuntu, they give 49856400 and 81478800.
Why there is a difference of one hour for 1972, but no difference for 1971 ?
Both systems have jq-1.6.
Update 1
Windows behaves the same way as MacOS.
Update 2
The dates where difference happens are as follows :
1972-03-20 - 1972-10-29 (inclusive)
...
2022-03-28 - 2022-10-30
So it seems MacOS/Windows implementations apply one hour on DST dates from 1972 onwards, but not for the years 1969,1970, 1971.
Whereas Ubuntu implementation does not apply at all.

The "master" version of jq fixes the issue (*). It's nice when jq and gojq agree:
$ uname -a
Darwin Mac-mini.local 21.6.0 Darwin Kernel Version 21.6.0 ...
$ jqMaster -nM '"1971-08-01T01:00:00Z","1972-08-01T01:00:00Z" | fromdateiso8601'
49856400
81478800
$ gojq -n '"1971-08-01T01:00:00Z","1972-08-01T01:00:00Z" | fromdateiso8601'
49856400
81478800
——
(*)
https://github.com/stedolan/jq/commit/3c5b1419a278dfb192666b33197dc182c670290d

Related

Last Month Date in Solaris CSH script

As pre requirement, I need to fetch last month date in Unix (solaris) csh.
set Lmit_Date=`date --date='1 month ago' +%Y%m%d`
above command will fetch last month date and working fine in Linux server. But our server is Solaris and mentioned command is not working.
Please can anyone suggest how I can fetch the last month date
The issue is due to the fact you are using a GNU date extension. --date is non standard.
Moreover, due to the fact month lengths are variable, the date displayed by GNU date might be unexpected, to say the least...
For example today is March 31 but "last month" date was March the 2nd according to GNU date:
$ date +%Y%m%d
20160331
$ date --date='1 month ago' +%Y%m%d
20160302
If you still want to either use GNU date on Solaris or find some workarounds, have a look to these replies:
https://stackoverflow.com/a/23507108/211665 and https://stackoverflow.com/a/17817087/211665
You should be able to compile coreutils for your solaris platform, which will provide you with the right date utility. But as coreutils overwrites core utilities as the name says, you may want to install this into a custom path and select the right date command through your special path, say "/opt/coreutils/bin/date".
The other method would be to calculate last month with a symbolic date output split
eval `date +"set YEAR=%Y; set MONTH=%m ;set DAY=%d"`
Now you can operate on "$YEAR", "$MONTH" and "$DAY". For example
let 'MONTH--'
if [ "$MONTH" -eq 0 ]; then MONTH=12; let 'YEAR--'; fi
set Lmit_Date=`date --date "$MONTH$DAY0000$YEAR" +"%Y%m%d"`
kind of. (I'm used to bash so I don't know if let is available here. But there are some other methods to shell calculations. There might be another keyword for csh).
Also you need to take care for number of days per month with the $DAY parameter.
function last_day {
y=`echo $1 | cut -f1 -d "-"`
m=`echo $1 | cut -f2 -d "-"`
d=`cal ${m} ${y} | nawk 'NF{A=$NF}END{print A}'`
echo "$y $m $d" | nawk '{printf("%s-%02d-%02d",$1,$2,$3);}'
} # last_day
last_day 2023-01-01
Will give you: 2023-01-31 in non-GNU Solaris.

use gpsd or cgps to return latitude and longitude then quit

I would like a dead-simple way to query my gps location from a usb dongle from the unix command line.
Right now, I know I've got a functioning software and hardware system, as evidenced by the success of the cgps command in showing me my position. I'd now like to be able to make short requests for my gps location (lat,long in decimals) from the command line. my usb serial's path is /dev/ttyUSB0 and I'm using a Global Sat dongle that outputs generic NMEA sentences
How might I accomplish this?
Thanks
telnet 127.0.0.1 2947
?WATCH={"enable":true}
?POLL;
gives you your answer, but you still need to separate the wheat from the chaff. It also assumes the gps is not coming in from a cold start.
A short script could be called, e.g.;
#!/bin/bash
exec 2>/dev/null
# get positions
gpstmp=/tmp/gps.data
gpspipe -w -n 40 >$gpstmp"1"&
ppid=$!
sleep 10
kill -9 $ppid
cat $gpstmp"1"|grep -om1 "[-]\?[[:digit:]]\{1,3\}\.[[:digit:]]\{9\}" >$gpstmp
size=$(stat -c%s $gpstmp)
if [ $size -gt 10 ]; then
cat $gpstmp|sed -n -e 1p >/tmp/gps.lat
cat $gpstmp|sed -n -e 2p >/tmp/gps.lon
fi
rm $gpstmp $gpstmp"1"
This will cause 40 sentences to be output and then grep lat/lon to temporary files and then clean up.
Or, from GPS3 github repository place the alpha gps3.py in the same directory as, and execute, the following Python2.7-3.4 script.
from time import sleep
import gps3
the_connection = gps3.GPSDSocket()
the_fix = gps3.DataStream()
try:
for new_data in the_connection:
if new_data:
the_fix.refresh(new_data)
if not isinstance(the_fix.TPV['lat'], str): # check for valid data
speed = the_fix.TPV['speed']
latitude = the_fix.TPV['lat']
longitude = the_fix.TPV['lon']
altitude = the_fix.TPV['alt']
print('Latitude:', latitude, 'Longitude:', longitude)
sleep(1)
except KeyboardInterrupt:
the_connection.close()
print("\nTerminated by user\nGood Bye.\n")
If you want it to close after one iteration also import sys and then replace sleep(1) with sys.exit()
much easier solution:
$ gpspipe -w -n 10 | grep -m 1 lon
{"class":"TPV","device":"tcp://localhost:4352","mode":2,"lat":11.1111110000,"lon":22.222222222}
source
You can use my script : gps.sh return "x,y"
#!/bin/bash
x=$(gpspipe -w -n 10 |grep lon|tail -n1|cut -d":" -f9|cut -d"," -f1)
y=$(gpspipe -w -n 10 |grep lon|tail -n1|cut -d":" -f10|cut -d"," -f1)
echo "$x,$y"
sh gps.sh
43.xx4092000,6.xx1269167
Putting a few of the bits of different answers together with a bit more jq work, I like this version:
$ gpspipe -w -n 10 | grep -m 1 TPV | jq -r '[.lat, .lon] | #csv'
40.xxxxxx054,-79.yyyyyy367
Explanation:
(1) use grep -m 1 after invoking gpspipe, as used by #eadmaster's answer, because the grep will exit as soon as the first match is found. This gets you results faster instead of having to wait for 10 lines (or using two invocations of gpspipe).
(2) use jq to extract both fields simultaneously; the #csv formatter is more readable. Note the use of jq -r (raw output), so that the output is not put in quotes. Otherwise the output would be "40.xxxx,-79.xxxx" - which might be fine or better for some applications.
(3) Search for the TPV field by name for clarity. This is the "time, position, velocity" record, which is the one we want for extracting the current lat & lon. Just searching for "lat" or "lon" risks getting confused by the GST object that some GPSes may supply, and in that object, 'lat' and 'lon' are the standard deviation of the position error, not the position itself.
Improving on eadmaster's answer here is a more elegant solution:
gpspipe -w -n 10 | jq -r '.lon' | grep "[[:digit:]]" | tail -1
Explanation:
Ask from gpsd 10 times the data
Parse the received JSONs using jq
We want only numeric values, so filter using grep
We want the last received value, so use tail for that
Example:
$ gpspipe -w -n 10 | jq -r '.lon' | grep "[[:digit:]]" | tail -1
28.853181286

Making the "ls" command sort "a" before "B" (vs a->b->A->B)

I am trying to find a way to have the results of an ls command be printed in a case insensitive manner.
currently an ls command results in:
Apple
Boy
Chart
Dock
apples
boys
charts
docks
what i want is this:
Apple
apples
Boy
boys
Chart
charts
Dock
docks
is this possible?
ls (at least if you're using the GNU coreutils version; ls --version to check that) sorts file names according to the current locale.
The set of available locales varies from system to system (locale -a for a list), but on my system this:
LC_COLLATE=en_US.utf8 ls
sorts names with a and A before b and B -- though it might not be exactly in the order you're looking for.
This works even when ls lists files in multiple columns, something that's difficult to do with sort -f.
(I have $LC_COLLATE set to C specifically so that locale-sensitive sorting is done in ASCII order.)
Just pipe the result to sort -f.
As a follow up to [Keith Thompson]'s answer, I tested on a Linux system and LC_COLLATE=C did not work for me, but LC_COLLATE="en_US.UTF-8" did. I put the following in my startup script:
export LANG=en_US.UTF-8
export LC_COLLATE="en_US.UTF-8"
This did not work on OS X.
# alias ll='(LC_COLLATE=en_US.utf8 && export LC_COLLATE && shopt -s nocaseglob && /bin/ls -alF --color=auto )'
# ll
ls --format=single-column | sort -f
Add to .profile:
alias llg='ls -ltr | grep -i'
then you can use following command:
llg "week"

How to colorize diff on the command line

When I have a diff, how can I colorize it so that it looks good?
I want it for the command line, so please no GUI solutions.
Man pages for diff suggest no solution for colorization from within itself. Please consider using colordiff. It's a wrapper around diff that produces the same output as diff, except that it augments the output using colored syntax highlighting to increase readability:
diff old new | colordiff
or just:
colordiff old new
Installation:
Ubuntu/Debian: sudo apt-get install colordiff
OS X: brew install colordiff or port install colordiff
Use Vim:
diff /path/to/a /path/to/b | vim -R -
Or better still, VimDiff (or vim -d, which is shorter to type) will show differences between two, three or four files side-by-side.
Examples:
vim -d /path/to/[ab]
vimdiff file1 file2 file3 file4
Actually there seems to be yet another option (which I only noticed recently, when running into the problem described above):
git diff --no-index <file1> <file2>
# output to console instead of opening a pager
git --no-pager diff --no-index <file1> <file2>
If you have Git around (which you already might be using anyway), then you will be able to use it for comparison, even if the files themselves are not under version control. If not enabled for you by default, then enabling color support here seems to be considerably easier than some of the previously mentioned workarounds.
diff --color option (added to GNU diffutils 3.4 in 2016-08-08)
This is the default diff implementation on most distributions, which will soon be getting it.
Ubuntu 18.04 (Bionic Beaver) has diffutils 3.6 and therefore has it.
On 3.5 it looks like this:
Tested with:
diff --color -u \
<(seq 6 | sed 's/$/ a/') \
<(seq 8 | grep -Ev '^(2|3)$' | sed 's/$/ a/')
Apparently added in commit c0fa19fe92da71404f809aafb5f51cfd99b1bee2 (Mar 2015).
Word-level diff
Like diff-highlight. It is not possible it seems, but there is a feature request: https://lists.gnu.org/archive/html/diffutils-devel/2017-01/msg00001.html
Related questions:
Using 'diff' (or anything else) to get character-level diff between text files
https://unix.stackexchange.com/questions/11128/diff-within-a-line
https://superuser.com/questions/496415/using-diff-on-a-long-one-line-file
ydiff does it though. See below.
ydiff side-by-side word level diff
https://github.com/ymattw/ydiff
Is this nirvana?
python3 -m pip install --user ydiff
diff -u a b | ydiff -s
Outcome:
If the lines are too narrow (default 80 columns), fit to the screen with:
diff -u a b | ydiff -w 0 -s
Contents of the test files:
a
1
2
3
4
5 the original line the original line the original line the original line
6
7
8
9
10
11
12
13
14
15 the original line the original line the original line the original line
16
17
18
19
20
b
1
2
3
4
5 the original line the original line the original line the original line
6
7
8
9
10
11
12
13
14
15 the original line the original line the original line the original line
16
17
18
19
20
ydiff Git integration
ydiff integrates with Git without any configuration required.
From inside a Git repository, instead of git diff, you can do just:
ydiff -s
and instead of git log:
ydiff -ls
See also: How can I get a side-by-side diff when I do "git diff"?
Tested on Ubuntu 16.04 (Xenial Xerus), Git 2.18.0, and ydiff 1.1.
And for those occasions when a yum install colordiff or an apt-get install colordiff is not an option due to some insane constraint beyond your immediate control, or you're just feeling crazy, you can reinvent the wheel with a line of sed:
sed 's/^-/\x1b[41m-/;s/^+/\x1b[42m+/;s/^#/\x1b[34m#/;s/$/\x1b[0m/'
Throw that in a shell script and pipe unified diff output through it.
It makes hunk markers blue and highlights new/old filenames and added/removed lines in green and red background, respectively.1 And it will make trailing space2 changes more readily apparent than colordiff can.
1 Incidentally, the reason for highlighting the filenames the same as the modified lines is that to correctly differentiate between the filenames and the modified lines requires properly parsing the diff format, which is not something to tackle with a regex. Highlighting them the same works "well enough" visually and makes the problem trivial. That said, there are some interesting subtleties.
2 But not trailing tabs. Apparently tabs don't get their background set, at least in my xterm. It does make tab vs. space changes stand out a bit though.
Coloured, word-level diff ouput
Here's what you can do with the the below script and diff-highlight:
#!/bin/sh -eu
# Use diff-highlight to show word-level differences
diff -U3 --minimal "$#" |
sed 's/^-/\x1b[1;31m-/;s/^+/\x1b[1;32m+/;s/^#/\x1b[1;34m#/;s/$/\x1b[0m/' |
diff-highlight
(Credit to #retracile's answer for the sed highlighting)
You can change the Subversion configuration to use colordiff:
~/.subversion/config.diff
### Set diff-cmd to the absolute path of your 'diff' program.
### This will override the compile-time default, which is to use
### Subversion's internal diff implementation.
-# diff-cmd = diff_program (diff, gdiff, etc.)
+diff-cmd = colordiff
via: https://gist.github.com/westonruter/846524
I use grc (Generic Colouriser), which allows you to colour the output of a number of commands including diff.
It is a Python script which can be wrapped around any command. So instead of invoking diff file1 file2, you would invoke grc diff file1 file2 to see colourised output. I have aliased diff to grc diff to make it easier.
Here is another solution that invokes sed to insert the appropriate ANSI escape sequences for colors to show the +, -, and # lines in red, green, and cyan, respectively.
diff -u old new | sed "s/^-/$(tput setaf 1)&/; s/^+/$(tput setaf 2)&/; s/^#/$(tput setaf 6)&/; s/$/$(tput sgr0)/"
Unlike the other solutions to this question, this solution does not spell out the ANSI escape sequences explicitly. Instead, it invokes the tput setaf and tput sgr0 commands to generate the ANSI escape sequences to set an appropriate color and reset terminal attributes, respectively.
To see the available colors for each argument to tput setaf, use this command:
for i in {0..255}; do tput setaf $i; printf %4d $i; done; tput sgr0; echo
Here is how the output looks:
Here is the evidence that the tput setaf and tput sgr0 commands generate the appropriate ANSI escape sequences:
$ tput setaf 1 | xxd -g1
00000000: 1b 5b 33 31 6d .[31m
$ tput setaf 2 | xxd -g1
00000000: 1b 5b 33 32 6d .[32m
$ tput setaf 6 | xxd -g1
00000000: 1b 5b 33 36 6d .[36m
$ tput sgr0 | xxd -g1
00000000: 1b 28 42 1b 5b 6d .(B.[m
Since wdiff accepts arguments specifying the string at the beginning and end of both insertions and deletions, you can use ANSI color sequences as those strings:
wdiff -n -w $'\033[30;41m' -x $'\033[0m' -y $'\033[30;42m' -z $'\033[0m' file1 file2
For example, this is the output of comparing two CSV files:
Example from 2.2 Actual examples of wdiff usage.
I would suggest you to give diff-so-fancy a try. I use it during my work and it sure seems great as of now. It comes packed with many options and it's really easy to configure your diffs the way you want.
You can install it by:
sudo npm install -g diff-so-fancy
or on Mac:
brew install diff-so-fancy
Afterwards, you can highlight your diffs like this:
diff -u file1 file2 | diff-so-fancy
Character-level color diff:
Install ccdiff
ccdiff -r /usr/share/dict/words /tmp/new-dict
No one has mentioned delta so far. It supports syntax colored diff view with syntax highlighting.
With the bat command:
diff file1 file2 | bat -l diff
On recent versions of Git on Ubuntu, you can enable diff-highlighting with:
sudo ln -s /usr/share/doc/git/contrib/diff-highlight/diff-highlight /usr/local/bin
sudo chmod a+x /usr/share/doc/git/contrib/diff-highlight/diff-highlight
And then adding this to your .gitconfig file:
[pager]
log = diff-highlight | less
show = diff-highlight | less
diff = diff-highlight | less
It's possible the script is located somewhere else in other distributions. You can use locate diff-highlight to find out where.
My favorite choice is vdiff <file1> <file2> function (I forgot from where I got it).
It will open two windows in Vim side-by-side, to see clearly see the difference between the two files.
vdiff () {
if [ "${#}" -ne 2 ] ; then
echo "vdiff requires two arguments"
echo " comparing dirs: vdiff dir_a dir_b"
echo " comparing files: vdiff file_a file_b"
return 1
fi
local left="${1}"
local right="${2}"
if [ -d "${left}" ] && [ -d "${right}" ]; then
vim +"DirDiff ${left} ${right}"
else
vim -d "${left}" "${right}"
fi
}
Put this script in your (.alias) or (.zshrc), and then call it using
vdiff <file1> <file2>.
Example
The results are:
diff --color=always file_a file_b | less
works for me
For me I found some solutions: it is a working solution
#echo off
Title a game for YouTube
explorer "https://thepythoncoding.blogspot.com/2020/11/how-to-echo-with-different-colors-in.html"
SETLOCAL EnableDelayedExpansion
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
set "DEL=%%a"
)
echo say the name of the colors, don't read
call :ColorText 0a "blue"
call :ColorText 0C "green"
call :ColorText 0b "red"
echo(
call :ColorText 19 "yellow"
call :ColorText 2F "black"
call :ColorText 4e "white"
goto :Beginoffile
:ColorText
echo off
<nul set /p ".=%DEL%" > "%~2"
findstr /v /a:%1 /R "^$" "%~2" nul
del "%~2" > nul 2>&1
goto :eof
:Beginoffile

How to use the S-output-modifier with Unix/Linux command ps?

The command
ps -o time -p 21361
works; however what I need is the running time of the process including all
the children. For example, if 21361 is a bash script, which calls other scripts,
then I want the total running time, including the running time of all children.
Now the ps documentation lists the "OUTPUT MODIFIER":
S
Sum up some information, such as CPU usage, from dead child processes into their parent. This is useful for examining a system where a parent process repeatedly forks off short-lived children to do work.
Sounds just right. Unfortunately, there is no specification of the ps-syntax, so
I have no clue where to place the "S"! For hours now I tried many combinations, but
either I get syntax errors, or "S" makes nothing. And on the Internet you find only
very basic information about ps (and always the same), specifically the "S" modifier
I couldn't find mentioned anywhere, and also nobody ever explains the syntax of ps.
I am not sure, but it might be that ps is somewhat buggy in this respect. Try this here:
$ ps p 12104 k time
PID TTY STAT TIME COMMAND
12104 ? Ss 16:17 /usr/sbin/apache2 -k start
$ ps p 12104 k time S
PID TTY STAT TIME COMMAND
12104 ? Ss 143:16 /usr/sbin/apache2 -k start
This is using the BSD options for ps. It works on my machine, however you get an extra header row and extra columns. I would cut them away using tr and cut:
$ ps p 12104 k time S | tail -n 1 | tr -s '[:space:]' | cut -d ' ' -f 4
143:39
$ ps p 12104 k time | tail -n 1 | tr -s '[:space:]' | cut -d ' ' -f 4
16:17
On MacOS X (10.7, Lion) the manual page says:
-S Change the way the process time is calculated by summing all exited children to their parent process.
So, I was able to get output using:
$ ps -S -o time,etime,pid -p 305
TIME ELAPSED PID
0:00.12 01-18:31:07 305
$
However, that output was not really any different from when the '-S' option was omitted.
I tried:
$ ps -S -o time,etime,pid -p 305
TIME ELAPSED PID
0:00.14 01-18:43:59 305
$ time dd if=/dev/zero of=/dev/null bs=1m count=100k
102400+0 records in
102400+0 records out
107374182400 bytes transferred in 15.374440 secs (6983941055 bytes/sec)
real 0m15.379s
user 0m0.056s
sys 0m15.034s
$ ps -S -o time,etime,pid -p 305
TIME ELAPSED PID
0:00.14 01-18:44:15 305
$
As you can see, the 15 seconds of system time spent copying /dev/zero to /dev/null did not get included in the summary.
At this stage, the only way of working out what the '-S' option does, if anything, is to look at the source. You could look for sumrusage in the FreeBSD version, for example, at FreeBSD.

Resources