Bash скрипт / awk для ввода и вывода файла CSV
У меня возникли проблемы с созданием сценария bash / awk / sed, который будет принимать CSV-файл с разделителями-запятыми из трех столбцов (имя, фамилию, дату рождения) и выводит другой CSV-файл с теми же столбцами из ввода с дополнительный столбец, показывающий разницу между текущей датой и датой рождения в годах.
$ yourscript <input CSV file> <output CSV file>
input.csv может выглядеть так:
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972
output.csv должен выглядеть так:
bob,wag,06/13/1958,62
ashley,hay,01/23/1983,37
evan,bert,09/11/1972,48
Ответы
$ cat data
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972
Для вывода в файл с именем output-fileи одновременного отображения в STDOUT:
$ awk -v year=$(\date +%Y) 'BEGIN{FS="/"} {print $0 "," year-$3}' data | tee output-file
bob,wag,06/13/1958,62
ashley,hay,01/23/1983,37
evan,bert,09/11/1972,48
Или просто вывести в тот же файл:
$ awk -v year=$(\date +%Y) 'BEGIN{FS="/"} {print $0 "," year-$3}' data > output-file
Для выполнения более точных вычислений времени, вы можете использовать gawk«s время и строковые функции (за @ предложение AdminBee в). Использование входных данных как:
$ cat data
bob,wag,06/13/1958
ashley,hay,01/23/1983
evan,bert,09/11/1972
Вы можете получить разницу во времени в днях между настоящим моментом и датой, указанной в каждой строке, с помощью:
$ awk -F, 'BEGIN{today=systime()}
{print $0 "," int((today-mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00))/(3600*24))}' \
data | tee output-file
bob,wag,06/13/1958,22755
ashley,hay,01/23/1983,13765
evan,bert,09/11/1972,17551
Фрагмент:
int((today-mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00))/(3600*24))
выполняет три основных действия для каждой строки входного файла:
- он вычисляет время, прошедшее (в секундах) с 1970-01-01 00:00:00 UTC (в системах POSIX), не считая дополнительных секунд, с
mktime(substr($3,7,4)" "substr($3,1,2)" "substr($3,4,2)" "00" "00" "00) - он вычисляет разницу во времени между указанным выше количеством и переменной
today, которая содержит количество секунд, прошедших во время выполнения с 1970-01-01 00:00:00 UTC. - он делит разницу во времени в секундах на 3600 * 24, чтобы получить то же самое в днях, и учитывает только целую часть результата, чтобы получить целые дни
int().
Вы можете поиграть с этим, чтобы получить разницу во времени в секундах, минутах, часах в зависимости от ваших потребностей. HTH
Чтобы получить разницу в датах, вы можете использовать эту небольшую функцию bash
Используйте следующие номера для ваших нужд
- # Чтобы получить разницу в днях : 86400
- # По получить Years разницу: 31536000
Функция Bash
datediff() {
current_date=$(date -d "$1" +%s)
birth_date=$(date -d "$2" +%s)
echo $(( (current_date - birth_date) / 31536000)) Years
}
Применение:
datediff '9/28/2020' '1/1/1999'
Вывод:
21 years
В зависимости от того, чего вы действительно хотите:
разница в годах:
(echo "firstname,lastname,d"; cat input.csv) | csv-sqlite \
"select *, strftime('%Y', 'now') - substr(d, 7, 4) as year_diff
from input" | csv-header --remove
возраст:
(echo "firstname,lastname,d"; cat input.csv) | csv-sqlite
"select *, strftime('%Y', 'now') - substr(d, 7, 4) -
case when strftime('%m%d', 'now') >= (substr(d, 1, 2) || substr(d, 4, 2))
then 0 else 1 end as age
from input" | csv-header --remove
csv-sqlite и csv-header взяты из csv-nix-tools