
У меня есть переменная, назначенная возвращаемой строке:
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)}
решение1
Попробуй использовать:
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/'
решение2
Вы можете использовать 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) }
в конце файла (после того, как последняя строка была прочитана и обработана) печатает последние два символа последней сохраненной строки. Печатает пустую строку, если не было более раннего успешного совпадения.
решение3
Это более эффективно, особенно еслифайл.csvбольшой и искомая строка находится ближе к концу:
ytd_wk="$(tac file.csv | grep -m 1 $(date +'%Y') | grep -o '..$')"
Как это работает: tac
выходыфайл.csvв обратном порядке и grep -m 1
находит первый экземпляр шаблона, который передается в grep -o
строку, выводит только два последних символа.