#linux #bash #for-loop #awk
Вопрос:
Доброе утро. У меня есть два текстовых файла с именем a.txt
и b.txt
, которые содержат данные в следующем формате, как показано ниже
year mn dt hr:mn:sec
xxxx-xx-xx xx:xx:xx.xxxxxx
Мой a.txt файл является
2019-01-01 00:58:49.925000
2019-01-01 01:48:39.665000
2019-01-01 15:42:18.955000
2019-01-01 18:40:49.915000
2019-01-01 18:47:00.735000
2019-01-01 21:07:49.255000
2019-01-01 21:52:29.055000
2019-01-02 03:19:54.955000
2019-01-02 07:41:27.845000
2019-01-02 18:52:32.995000
И b.txt файл содержит
2019-01-01 00:58:50.565000
2019-01-01 01:48:39.915000
2019-01-01 04:09:53.705000
2019-01-01 06:28:07.515000
2019-01-01 15:43:13.455000
2019-01-01 18:40:53.255000
2019-01-01 18:47:04.005000
2019-01-01 18:47:03.975000
2019-01-01 21:07:53.725000
2019-01-01 21:52:37.195000
2019-01-02 07:41:34.255000
2019-01-02 19:41:08.865000
Кроме того, каждый из текстовых файлов (a.txt и b.txt) содержит 14 строк, включая пробел.
Теперь я хочу рассчитать разницу во времени между каждой строкой ( a.txt-b.txt
) в секундах, и я хочу добавить строки в новый текстовый файл c.txt который должен содержать только строки с разницей во времени от 3 до 18 секунд.
Я сделал что-то вроде следующего:
#!/bin/sh
a=`cat a.txt`
b=`cat b.txt`
awk '{print $a-$b}'
Комментарии:
1. Что должно произойти, если одна из дат пуста? Например, в третьей строке ваших файлов примеров.
2. А как насчет пустых строк? Как вы хотите их различать?
a.txt
имеет 10 дат, тогдаb.txt
как имеет 12 дат.3. если пустые результаты должны быть равны нулю
4. Что вы подразумеваете под пустыми результатами ? пустые строки? Предполагается, что даты для пустых строк равны 0? Или просто верните 0?
5. да..я предполагаю, что для пустых строк значение равно нулю, так как значение строк не показывает, что его результаты должны быть равны нулю
Ответ №1:
Использование GNU awk для mktime() на основе одной из возможных интерпретаций вашего вопроса:
$ cat tst.awk
!NF { next }
{ gsub(/[-:]/," ") }
NR==FNR {
file1[NR] = $0
next
}
FNR in file1 {
diff = mktime($0) - mktime(file1[FNR])
if ( (3 <= diff) amp;amp; (diff <= 18) ) {
print diff
}
}
$ awk -f tst.awk a.txt b.txt
4
4
4
8
7
Очевидно, просто добавьте > c.txt
, чтобы перенаправить вывод.
Если это не то, что вам нужно, отредактируйте свой вопрос, чтобы уточнить свои требования и предоставить ожидаемый результат с учетом опубликованного вами образца ввода.
Ответ №2:
Преобразуйте каждую дату в время unix с помощью date -d "2019-01-01 …" %s
. Затем вычтите время unix. При этом учитываются только целые секунды. Ваши даты включают доли секунд. Если вы тоже хотите использовать дроби, измените %s
на %s.%N
.
Следующий сценарий включает в себя все ваши дополнительные требования, см. раздел комментариев к этому ответу.
paste a.txt b.txt |
awk '
function inSecs(date) {
cmd = "date -d ""date"" %s"
cmd | getline unixTime
close(cmd)
return unixTime
}
{
if (NF == 4) {
diff = inSecs($1" "$2) - inSecs($3" "$4)
if (3 <= diff amp;amp; diff <= 18)
print $1 " " diff "sec"
}
}'
Комментарии:
1. но несколько раз в a.txt строка пропущена, в то время как в b.txt строка, присутствующая в этом случае, я хочу, чтобы вывод был равен нулю…пожалуйста, вы можете один раз изменить свой сценарий..
2. Однако мне нужно, чтобы дата была добавлена в формате гггг-мн-день до результатов, я имею в виду, что результаты должны быть примерно такими: 2019-01-01 1 сек
3. @dtutub Если вы задаете вопрос, пожалуйста, сделайте его полным, а не добавляйте в него что-то новое после каждого ответа. Тем не менее, я не понимаю ваш ожидаемый формат вывода. Если вы вычтете две даты
2019-01-02 03:04:05.0
, а2019-01-01 01:01:01.0
затем какой будет ожидаемый результат?4. пожалуйста, обновите ответ, сэр, так как мне также нужна дата. я сделал что-то вроде ошибки печати даты($1) — ошибки($2) …это не дает результатов, как я хотел бы
5. я думаю, что в моем случае даты похожи, меняется только время