Я нашел решение, которое мне подходит.
Сначала я изучил исходники mwm, libXm, libX11, чтобы понять, как заставить программы использовать курсоры меньшего размера. Я попробовал некоторые изменения, но понял, что это потребует много работы, перекомпиляции и т. д.
Затем я переименовал/удалил каталог /usr/share/icons/Adwaita/cursors
. Когда X больше не находил курсоры увеличенного размера, установленные пакетом adwaita-cursor-theme
, единственные оставшиеся не так красивы, как курсоры Adwaita, но по крайней мере имеют правильный размер.
Я считаю, что курсоры adwaita требуются для основных пакетов, поэтому я не могу позволить себе удалить пакет adwaita-cursor-theme
. У меня есть два варианта:
Окончательное решение:Я скачал исходники темы adwaita и создал новые курсоры. Есть файлы *.in
, в которых указаны размеры курсора. Я отредактировал эти файлы, чтобы удалить курсоры большого размера, и создал новые курсоры с make.sh
, что в основном вызывает xcursorgen
для каждого курсора. Я поместил эти курсоры в /usr/share/icons/Adwaita/cursors
, и теперь у меня есть курсоры нужного мне размера.
Цикл не может знать, когда он дойдет до конца, если он действительно не дойдет до конца. Таким образом, либо вы обрабатываете свой файл дважды, один раз, чтобы получить количество строк, а другой — для вывода, либо вы печатаете предыдущее значение на каждой итерации, а последнее — при выходе из цикла :
.prev=""
while read direction; do
if [ -n "$prev" ]; then
echo "Direction: $prev"
fi
prev="$direction"
done < direction
echo "Last Direction: $prev"
Вы можете считать значения в массив, а затем использовать длину массива:
#!/bin/bash
i=0
while read line ; do
arr[$i]="$line"
((i++))
done <file
for (( i=0 ; i<=${#arr[@]}-2 ; i++ )) ; do
echo Direction: ${arr[i]}
done
echo Last direction: ${arr[-1]}
Конечно, это означает, что все данные должны находиться в оперативной памяти.
Более простой arr=( $(cat file) )
будет работать только в том случае, если строки не содержат пробелов, поэтому здесь я использовал цикл while read
-.
Вы можете использовать сочетание paste
, tail
и head
:
$ paste -s -d'\n' <(head -n -1 direction | sed 's/^/Direction: /') <(tail -n1 direction | sed 's/^/Last direction: /')
Direction: east
Direction: north
Direction: south
Direction: west
Last direction: south-west
paste -s -d'\n'
использует новую строку в качестве разделителя с опцией -d'\n'
и опцией-s
:
-s, --serial
paste one file at a time instead of in parallel
head -n -1
извлекает все строки, кроме последней, затем передается в sed
для выполнения нужной команды только в этих строках.
tail -n1 file
извлекает последнюю строку файла, затем передается в sed
для выполнения нужной команды только в этой строке.
Или, более кратко, просто используя cat
вместо paste
, как отмечено в комментарии @Mick Matteo:
$ cat <(head -n -1 direction | sed 's/^/Direction: /') <(tail -n1 direction | sed 's/^/Last direction: /')
Вариант ответа FelixJN , чтение строк в массив, но с использованием встроенных функций bash вместо циклов bash:
mapfile -t DIR < direction
printf "Direction: %s\n" "${DIR[@]::${#DIR[@]}-1}"
printf "Last direction: %s\n" "${DIR[-1]}"
mapfile — это встроенная функция, добавленная в Bash 4, которая считывает стандартный ввод в массив с одной строкой на запись. Опция -t
удаляет символы новой строки.
printf
будет многократно применять свою строку формата, пока не израсходует всю свою входные аргументы.
Расширение ответов FelixJN и Ника Маттео:с использованием переносимых функций оболочки (с учетом того, что вопрос не имеет тегов, специфичных для оболочки -)и предполагая, что вы обрабатываете контролируемый, «достаточно маленький -» набор строк, вы можете узнать, когда цикл достигает своего последнего элемента, если поместите данные в массив позиционных параметров:
IFS='
'
set -f
set -- $(cat direction)
for dir
do
if [ $(( i = i + 1 )) -eq "$#" ]
then
printf '%s' 'Last direction: '
else
printf '%s' 'Direction: '
fi
printf '%s\n' "$dir"
done
Имейте в виду, что вы можете захотеть правильно восстановитьIFS
после его установки.
Обратите внимание, однако, что это удалит все пустые входные строки из вывода. Если вас это не устраивает, вы можете загрузить массив позиционных параметров в цикле:
set --
while IFS= read -r line
do
set -- "$@" "$line"
done <direction
(Нет необходимости устанавливать IFS
на новую строку и set -f
в данном случае ).
Подход из ответов cas(sed
part )и terdon — обработка последнего элемента «вне» цикла — также может быть реализован в AWK с использованием довольно распространенного шаблона:
awk '
NR > 1 { print "Direction: " dir }
{ dir = $0 }
END { if (NR > 0) print "Last direction: " dir }
' direction
col=`awk 'END{print NR}' filename`
awk -v co="$col" '{if (NR<co){print "Direction: "$0}else{print "Last direction: "$0}}' filename
output
Direction: east
Direction: north
Direction: south
Direction: west
Last direction: south-west
Один из способов — зациклиться на строках и отложить печать строк на одну итерацию :мы печатаем предыдущую строку, сохраненную из переменной(prev
в коде ниже ), а затем сохраняем текущую строку в этом потом переменная. После завершения цикла у нас есть последняя строка в prev
, и мы можем вывести ее со специальным префиксом :
#! /bin/sh
prev=""
first="yes"
# from https://stackoverflow.com/a/1521498/648741
while IFS="" read -r p || [ -n "$p" ]; do
if [ "$first" = "yes" ]; then
first="no"
else
printf 'Direction: %s\n' "$prev"
fi
prev="$p"
done < directions
if [ "$first" = "no" ]; then
printf 'Last direction: %s\n' "$prev"
fi
Код здесь уделяет особое внимание тому, чтобы не повредить пробелы и разрешить знаки доллара в строках. Если в этом нет необходимости, работает и более простой вариант:
#! /bin/sh
prev=""
while read -r p; do
if [ -n "$prev" ]; then
echo "Direction: $prev"
fi
prev="$p"
done < directions
if [ -n "$prev" ]; then
echo "Last direction: $prev"
fi
Использование Raku (, ранее известного как Perl _6)
raku -e 'my $fh = $*ARGFILES.IO.open; $fh.eof ?? put("Last direction: $_") !! put("Direction: $_") for $fh.lines; $fh.close;' file.txt
ИЛИ
raku -e 'my $fh = $*ARGFILES.IO.open; for $fh.lines() { if not $fh.eof { put "Direction: $_" } else { put "Last direction: $_" };}; $fh.close;' file.txt
Пример ввода:
east
north
south
west
south-west
Пример вывода:
Direction: east
Direction: north
Direction: south
Direction: west
Last direction: south-west
В настоящее время Raku реализует метод .eof
, который работает с объектами IO::Handle
или IO::CatHandle
и "...возвращает True
, если операции чтения исчерпали содержимое дескриптора...."
В первом примере кода выше используется тернарный оператор Раку $condition ?? $true !! $false
для проверки того, является ли $fh.eof
True
. Обратите внимание выше для обоих примеров кода, как .eof
работает непосредственно со скаляром дескриптора файла $fh
, тогда как $_
загружается с извлеченными (строковыми -мудрыми )данными, которые печатаются с использованиемput
(или say
, при желании ).
Обратите внимание, что приведенные выше довольно упрощенные примеры кода работают только с одним файлом за раз в командной строке bash
. Однако вполне вероятно, что передача списка файлов в $fh
(, например, с помощью метода Раку dir()
), может быть лучшим способом манипулирования несколькими файлами одновременно.
https://docs.raku.org/routine/eof
https://docs.raku.org/language/operators#index-entry-operator_ternary
https://raku.org