У меня есть переменная, назначенная возвращаемой строке:

ytd_wk=$(cat file.csv | grep $(date +'%Y') | tail -1)

Я хочу подстроку последних 2 символов:

ytd_wk=${ytd_wk:(-2)}

Есть ли способ использовать однострочный для достижения этого? Я пробовал ниже, но получил ошибку bad substitution:

ytd_wk=${$(cat file.csv | grep $(date +'%Y') | tail -1):(-2)}

2
lovechillcool 21 Ноя 2017 в 04:53
2
Как вы определяете «однострочный»? Вы можете просто объединить первые две команды в одну строку, разделив их && или ;.
 – 
G-Man Says 'Reinstate Monica'
21 Ноя 2017 в 00:03

3 ответа

Лучший ответ

Попробуй использовать:

grep "$(date +'%Y')" file.csv | tail -1 | sed 's/.*\(..$\)/\1/'

Вам не нужен cat, потому что grep может получать данные как из вывода другой программы, так и из определенного файла. Последний способ более эффективен, так как использует только одну команду, а это более быстро и потребляет меньше системных ресурсов.

Полное решение:

ytd_wk=$(grep "$(date +'%Y')" file.csv | tail -1 | sed 's/.*\(..$\)/\1/')

Вы можете опустить tail с GNU sed '$!d':

grep "$(date +'%Y')" file.csv | sed -r '$!d;s/.*(..$)/\1/'

POSIX :

grep "$(date +'%Y')" file.csv | sed -e '$!d' -e 's/.*\(..$\)/\1/'
3
Egor Vasilyev 21 Ноя 2017 в 09:59
2
+1 за то, что вы не использовали cat в своем ответе - хотя было бы лучше, если бы вы объяснили, почему cat не нужен.
 – 
G-Man Says 'Reinstate Monica'
21 Ноя 2017 в 00:00

Вы можете использовать awk, комбинируя cat, grep, sed и tail других предложений:

awk -v year=$(date +'%Y') '$0 ~ year {line=$0} END {print substr(line,length(line)-1,2)}' file.csv

Напишите это шаг за шагом

  • -v year=$(date +'%Y') устанавливает переменную awk year в текущий год
  • $0 ~ year { line=$0 } применяется к каждой строке файла по очереди. Если в текущей строке есть совпадение с годом, оно сохраняется в переменной awk line
  • END { print substr(line,length(line)-1,2) } в конце файла (после того, как последняя строка была прочитана и обработана) печатает последние два символа самой последней сохраненной строки. Он печатает пустую строку, если ранее не было успешного совпадения.
1
roaima 21 Ноя 2017 в 02:47

Это более эффективно, особенно если файл file.csv большой и нужная строка ближе к концу:

ytd_wk="$(tac file.csv | grep -m 1 $(date +'%Y') | grep -o '..$')"

Как это работает: tac выводит file.csv в обратном порядке, а grep -m 1 находит первый экземпляр шаблона, который передается в grep -o, который выводит только последний два символа.

1
agc 21 Ноя 2017 в 12:25