Ищу способ добавить день недели в конец строки

EDID на моем мониторе был поврежден. Мой Macbook pro вообще перестал отображаться на мониторе через несколько месяцев после написания вышеуказанного поста, что побудило меня протестировать и мой рабочий стол, и ноутбук на телевизоре Vizio. Оба работали безупречно. Я не упомянул выше, что у меня также были Windows 10 и Linux на одной машине. Windows могла отображать правильно все время, что заставило меня думать, что это что-то помимо монитора. Оказывается, MacOS, Linux и Windows по-разному реагируют на повреждение EEPROM, содержащего информацию EDID. Windows, казалось, продолжала работать нормально, Mac в конечном итоге вообще перестал работать, а Linux будет отображаться, но с неправильным разрешением.

Я купил новый монитор, и все работает нормально.

0
07.11.2019, 13:11
4 ответа

С помощью GNU awkвы можете сделать:

gawk -i inplace -F, -v OFS=, -v date_field=4 '
  (t = mktime(gensub("-", " ", "g", $date_field) " 0 0 0")) > 0 {
    $NF = strftime("%A", t)};1' your-file
  • -i inplace:включает в -режим редактирования места gawk, при котором вывод записывается в новый файл, предназначенный для замены входного файла.
  • -F,и -v OFS=,устанавливают разделители полей ввода и вывода
  • mktime()— это расширение GNU awk, которое анализирует строку в формате year month day hour minute secondи возвращает соответствующее время эпохи Unix. Здесь,мы используемgensub()(другое расширение gawk ), чтобы заменить -пробелами в 4-м поле (YYYY-MM-DD), чтобы передать YYYY MM DD 0 0 0время в mktime().
  • (t = mktime(...)) > 0 {...}и 1— это две пары condition {action}, которые запускаются для каждой входной записи (здесь строки).

    • Для первого из них условие проверяет, больше ли значение, возвращаемое mktime()(, присвоенное t), чем 0(mktime()возвращает -1, если не удается проанализировать спецификацию даты ), и в этом случае запускается действие .strftime()(другое расширение gawk ), подобное его эквиваленту C, используется для форматирования времени (здесь время эпохи unix, хранящееся в tс форматом%A:локализованное название дня недели ). Результат присваиваем NF-му полю ($NF), NF— специальной переменной, которая содержит количество полей в текущей записи, а $— оператору для получения содержимого полей (или полной записи с$ 0).
    • во втором(1)отсутствует часть действие , которая по умолчанию{print}(печатает текущую запись ), а условие (1)всегда верно. Это идиоматический короткий способ безоговорочно распечатать текущую запись, если вы хотите быть более подробным, вы можете сделать:

      gawk -i inplace \
           -v FS=, \
           -v OFS=, \
           -v date_field=4 \
           -v current_record=0 \
           -v always=1 '
        {
          date_for_mktime = gensub("-", " ", "g", $date_field) " 0 0 0"
          unix_time = mktime(date_for_mktime)
        } 
        unix_time > 0 {
          $NF = strftime("%A", unix_time)
        }
        always {print $current_record}' your-file
      

Если вы хотите, чтобы названия дней недели всегда были на английском языке, независимо от локали пользователя, вы можете исправить локаль наC(LC_ALL=C gawk...).

4
28.01.2020, 02:14

С помощью "одного -лайнера" ​​наверное нельзя (Редактировать :оказалось можно, всё-таки ), но можно сделать это с помощью шелл-скрипта. Ядром является использование утилиты dateдля получения дня недели из даты, которую вы уже извлекли.

Для этого посмотрите на вывод

user@host $ date +%A -d 2019-07-14
Sunday

Используя это, вы можете написать сценарий, который считывает строку входного файла -, извлекает день недели для каждой строки, кроме заголовка, и записывает заголовок без изменений, а все остальные строки с днем ​​недели добавляются в другой файл.

#!/bin/bash

# Check if input and output filenames were specified
if [[ "$#" != "2" ]]
then
    echo "Usage: $0 <input filename> <output filename>"
    exit 1
fi

if [[ ! -e "$1" ]]
then
    echo "Error, $1 doesn't exist!"
    exit 1
fi

if [[ "$1" == "$2" ]]
then
    echo "Error, input and output filenames must not be equal!"#
    exit 1
fi



# Perform the actual transformation
while read input
do
    if [[ -n "$(grep "^Server" <<< $input)" ]]
    then
    echo "$input" > $2
    else
    date=$(awk '{match($0,",(20[[:digit:]]{2}-[[:digit:]]{2}-[[:digit:]]{2})",a); print a[1]}' <<< $input)
    wday=$(date +%A -d $date)
    echo "$input$wday" >> $2
    fi
done < $1

Объяснить

Первая часть — это проверки работоспособности ввода, они также могут выполняться иначе.

Вторая часть — это реальный цикл по строкам входного файла.

  • Сначала мы проверяем, является ли текущая строка «заголовком», используя grep, чтобы определить, начинается ли она со строки «Сервер». Если результатом grepявляется непустая строка -, запишите ее в выходной файл «как есть».
  • Затем используйте awk, чтобы найти шаблон «20YY -MM -DD», заключенный в запятую, и извлечь фактическое значение во внутренний массив a, который назначен переменной bash $date.
  • Эта переменная теперь используется в вызове date, как указано выше, для возврата дня недели.
  • Затем строка ввода с добавленным днем ​​недели записывается в выходной файл.
1
28.01.2020, 02:14

С Миллер(mlr):

mlr --csvlite put '
  $Hour = ""; $DOW = strftime(strptime($Datestamp,"%Y-%m-%d"),"%A")
' file.csv

Пр.

$ mlr --csvlite put '$Hour = ""; $DOW = strftime(strptime($Datestamp,"%Y-%m-%d"),"%A")' file.csv
Server ID,Make,"Server Room",Datestamp,Timestamp,Distance,Ping,Download,Upload,Payload,"Src IP Address",Hour,DOW
x6883101,HP,"Server Room A",2019-07-14,04:50:02,26.444,11.521,49193480,41904833,,192.168.1.1,,Sunday
s3398577,Dell,"Server Room B",2019-09-21,10:50:02,56.574,37.608,48955461,45858381,,192.168.1.1,,Saturday
x6883551,Dell,"Server Room A",2019-08-16,02:00:04,26.444,17.921,86551957,88775986,,192.168.1.1,,Friday
s1555023,HP,"Server Room C",2018-02-06,04:50:01,516.574,402.527,907658,608152,,192.168.1.1,,Tuesday
s3398023,HP,"Server Room B",2019-01-17,10:50:01,56.574,40.233,48484827,45620028,,192.168.1.1,,Thursday
s1555098,IBM,"Server Room C",2018-11-18,02:00:03,516.514,404.671,819027,601233,,192.168.1.1,,Sunday
x6883582,Dell,"Server Room A",2019-05-19,04:50:02,26.444,12.506,88871436,84360552,,192.168.1.1,,Sunday

Пакет millerдоступен в репозитории Ubuntu 16.04 universe.

1
28.01.2020, 02:14

Моя первая реакция была такой же, как у Стефана.

Perl тоже подойдет:

perl -MTime::Piece -F, -lape '
  if ($F[3] =~ /^[\d-]+$/) {
    $F[-1] = Time::Piece->strptime($F[3], "%Y-%m-%d")->strftime("%A");
    $_ = join ",", @F;
  }
' file
1
28.01.2020, 02:14

Теги

Похожие вопросы