Просто вставьте команду в цикл while
. Здесь есть ряд нюансов, но в основном (в bash
или любой оболочке POSIX):
longcommand |
while IFS= read -r line
do
whatever "$line"
done
Другая основная проблема с этим (кроме IFS
ниже) - это когда вы пытаетесь использовать переменные внутри цикла после его завершения. Это происходит потому, что цикл на самом деле выполняется в под-оболочке (просто другой процесс оболочки), из которой вы не можете получить доступ к переменным (также она завершается, когда завершается цикл, и в этот момент переменные полностью исчезают. Чтобы обойти это, вы можете сделать:
longcommand | {
while IFS= read -r line
do
whatever "$line"
lastline="$line"
done
# This won't work without the braces.
echo "The last line was: $lastline"
}
Пример Хауке о настройке lastpipe
в bash
является другим решением.
Чтобы убедиться, что вы обрабатываете вывод команды "по мере ее выполнения", вы можете использовать stdbuf
для установки stdout
процесса в режим линейной буферизации.
stdbuf -oL longcommand |
while IFS= read -r line
do
whatever "$line"
done
Это настроит процесс на запись одной строки за раз в трубу вместо внутренней буферизации вывода в блоки. Имейте в виду, что программа может сама изменить эту настройку. Аналогичного эффекта можно добиться с помощью unbuffer
(часть expect
) или script
.
stdbuf
доступен в системах GNU и FreeBSD, он влияет только на stdio
буферизацию и работает только для не-setuid, не-setgid приложений, которые динамически связаны (поскольку использует трюк LD_PRELOAD).
Попробуйте также
awk '
$1 != LAST {printf "%s%s ", LD, $1 # print every new COL1 value
LAST = $1 # and remeber it
LD = RS # set the line delimiter (empty at program start)
FD = "" # unset field delimiter
}
{printf "%s%s", FD, $2 # print successive second fields, after field delim
FD = "|" # set the field delimiter
}
END {printf RS # last action: new line
}
' file
FileA, CREATE|MODIFY|DELETE
FileB, CREATE|MODIFY
awk '1 {if (a[$1]) {a[$1] = a[$1]" "$2"|"} else {a[$1] = $2"|"}} END {for (i in a) { print i,a[i]}}' file |sed 's/.$//'
И четвертый :Д
awk '1 {if (a[$1]) {a[$1] = a[$1]$2"|"} else {a[$1] = $2"|"}} END {for (i in a) { print i,gensub( /\|$/,"","1",a[i])}}' kumarjit
FileA, CREATE|MODIFY|DELETE
FileB, CREATE|MODIFY
Для вывода в отсортированном порядке с помощью GNU awk
gawk -F', ' '
{ a[$1] = a[$1] "|" $2 }
END {
PROCINFO["sorted_in"] = "@ind_str_asc"
for (b in a) print b ", " substr(a[b], 2)
}
'
Для вывода в исходном порядке клавиш:
awk -F', ' '
!($1 in a) { keys[++count] = $1 }
{ a[$1] = a[$1] "|" $2 }
END {
for (i = 1; i <= count; i++)
print keys[i] ", " substr(a[keys[i]], 2)
}
'