Попробуйте приведенное ниже решение awk:
echo "Hello" | awk '{ for ( i=length($0);i>0;i-- ) { if (i == length($0) ) { printf "%s",toupper(substr($0,i,1)) } else { printf "%s",tolower(substr($0,i,1)) } } printf "\n" }'
Возьмите каждую букву слова посимвольно, начиная с последней. Если это последний символ, преобразуйте его в верхний регистр и напечатайте, иначе напечатайте нижний регистр.
Не совсем ответ, но слишком большой и требует форматирования, поэтому это не может быть комментарием, поэтому...
1.6M — это не так уж много строк. 1 миллион строк в час, как вы говорите, чрезвычайно медленный, 1 миллион строк в минуту был бы более чем разумным. Например, я создал файл длиной 1 600 000 строк, по 300 столбцов в каждой, запустив этот скрипт:
$ awk -v n=1600000 -v c=300 -v OFS='\t' 'BEGIN{for (j=1;j<=c;j++) printf "col%s%s",j,(j<c?OFS:ORS); for (i=1;i<=n;i++) for (j=1;j<=c;j++) printf "%s%s",j,(j<c?OFS:ORS)}' > file
а затем я запустил скрипт, чтобы выполнить преобразование в вашем вопросе в этом файле:
$ time awk 'BEGIN{FS=OFS="\t"} NR==1{split($0, headers); print; next} {for (i=166;i<=NF;i++) $i=headers[i] "|" $i } 1' file > out
real 1m22.569s
user 1m17.971s
sys 0m4.359s
Таким образом, это заняло около 82 секунд вместо 1,5 часов.
С GNU Parallel это выглядит примерно так:
#!/bin/bash
do_block() {
awk 'BEGIN{FS=OFS="\t"}
NR==1{split($0, headers); next}
{for (i=166;i<=NF;i++) $i=headers[i] "|" $i } 1'
}
export -f do_block
# Non-parallel version
cat file | head -n1 > out1
time cat file | do_block >> out1
# Parallel version
cat file | head -n1 > out2
time parallel -k --pipepart --block -30 -a file --header : do_block >> out2
На моем 4-ядерном процессоре параллельная версия примерно в 3 раза быстрее.