Відповіді:
Використання sed
для емуляції tac
:
sed '1!G;h;$!d' ${inputfile}
sed
однолінійний. Див. "36. Зворотний порядок рядків (емуляція" tac "Команда Unix)." у відомому седлайн-лайнері Пояснено для повного пояснення того, як це працює.
sort
- є ймовірність, що він використовуватиме тимчасовий файл).
З ed
:
ed -s infile <<IN
g/^/m0
,p
q
IN
Якщо ви ввімкнено BSD
/ OSX
(і, сподіваємось, незабаром на GNU
/ linux
теж, як це буде POSIX ):
tail -r infile
awk '{a[i++]=$0} END {for (j=i-1; j>=0;) print a[j--] }' file.txt
через awk один лайнер
awk 'a=$0RS a{}END{printf a}'
but your first
perl reverse <> `це найкраща / найшвидша відповідь на сторінці (для мене), в 10 разів швидше, ніж ця awk
відповідь (усі анкрети awk приблизно однакові, часом)
awk '{a[NR]=$0} END {while (NR) print a[NR--]}'
Як ви попросили зробити це в bash, ось рішення, яке не використовує awk, sed або perl, а лише функцію bash:
reverse ()
{
local line
if IFS= read -r line
then
reverse
printf '%s\n' "$line"
fi
}
Вихід
echo 'a
b
c
d
' | reverse
є
d
c
b
a
Як і очікувалося.
Але майте на увазі, що рядки зберігаються в пам'яті, по одному рядку в кожному рекурсивно називаному екземплярі функції. Тож обережно з великими файлами.
Ви можете передати це через:
awk '{print NR" "$0}' | sort -k1 -n -r | sed 's/^[^ ]* //g'
У awk
префікси кожен рядок з номером рядка з подальшим пропуском. sort
Змінює порядок рядків при сортуванні по першому полю (номер рядка) в зворотному порядку, числовий стиль. І sed
смужки відкреслити номери ліній.
Наступний приклад показує це в дії:
pax$ echo 'a
b
c
d
e
f
g
h
i
j
k
l' | awk '{print NR" "$0}' | sort -k1 -n -r | sed 's/^[^ ]* //g'
Він виводить:
l
k
j
i
h
g
f
e
d
c
b
a
cat -n
діє так, якawk '{print NR" "$0}'
У перл:
cat <somefile> | perl -e 'while(<>) { push @a, $_; } foreach (reverse(@a)) { print; }'
perl -e 'print reverse<>'
perl -pe '$\=$_.$\}{'
)
reverse<)
швидко: добре! але "по-справжньому потворний" надзвичайно повільний, оскільки кількість рядків збільшується. !! ....
-n
було зайвим, дякую.
sort
).
Рішення лише для BASH
читати файл у масив bash (один рядок = один елемент масиву) та друкувати масив у зворотному порядку:
i=0
while read line[$i] ; do
i=$(($i+1))
done < FILE
for (( i=${#line[@]}-1 ; i>=0 ; i-- )) ; do
echo ${line[$i]}
done
while..read
.
IFS=''
та read -r
не дозволяйте всілякі втечі та вилучення IFS від викручування. Я думаю, що bash mapfile ARRAY_NAME
вбудований є кращим рішенням для читання в масивах.
Bash, з mapfile
згадуваним у коментарях до fiximan, і насправді можливою кращою версією:
# last [LINES=50]
_last_flush(){ BUF=("${BUF[@]:$(($1-LINES)):$1}"); } # flush the lines, can be slow.
last(){
local LINES="${1:-10}" BUF
((LINES)) || return 2
mapfile -C _last_flush -c $(( (LINES<5000) ? 5000 : LINES+5 )) BUF
BUF=("${BUF[@]}") # Make sure the array subscripts make sence, can be slow.
((LINES="${#BUF[@]}" > LINES ? LINES : "${#BUF[@]}"))
for ((i="${#BUF[@]}"; i>"${#BUF[@]}"-LINES; i--)); do echo -n "${BUF[i]}"; done
}
Його продуктивність в основному порівнянна з sed
рішенням і стає швидшою, оскільки кількість запитуваних рядків зменшується.
Simple do this with your file to sort the data in reverse order, and it should be unique.
sed -n '1h; 1d; G; h; $ p'
як показано тут:
echo 'e
> f
> a
> c
> ' | nl | sort -nr | sed -r 's/^ *[0-9]+\t//'
Результат:
c a f e