Я мог бы подойти к этому с помощью awk таким образом:
-F,
"\""
. Скрипт:
awk -F, 'BEGIN{ OFS=FS } {$1="\""$1"\""; $5="\""$5"\""; $6="\""$6"\""; print }' < input.csv > output.csv
Когда вы обнаружите, что вам нужно указать больше полей, просто сделайте то же самое, что и с полями 1, 5 и 6 выше.
#!/bin/bash
mycmd() {
echo progress >&2
echo out
sleep 1
echo progress >&2
echo out
sleep 1
echo progress >&2
echo out
sleep 1
}
# Make sure the tempfile is made in a secure way that avoids indeterminism / potential race conditions / etc.
tmpfile="$(tempfile)"
# Write output to the file
mycmd 2>&1 >"$tmpfile"; cat "$tmpfile"; rm "$tmpfile"
# or if output is small: Write it to an environment variable.
# These are below the limit for "small" for different shells
# (Determined by making "mycmd" output that amount of data)
# ash 30 GB
# dash 30 GB
# bash 3 GB
# zsh 3 GB
# ksh 1 GB
out=`mycmd` 2>&1
echo "$out"
Оба решения будут видны пользователю root (в файловой системе и в /proc/ */environ )и никаким другим пользователям в системе.
Если в вашей системе есть sponge
и оболочка поддерживает /dev/stdout:
{
cmd 2>&3 3>&- |
sponge /dev/stdout 3>&-;
} 3>&1
(Версия Кш:
$ ksh --version
version sh (AT&T Research) 93u+ 2012-08-01
)
Вы должны сделать что-то вроде:
{
cmd 2>&3 3>&- |
awk ' {saved = saved $0 ORS}
END {printf "%s", saved}' 3>&-
} 3>&1
Здесь используется awk
для хранения всего вывода cmd
(после того, как cmd
записал свой вывод stderr в stdout )скрипта.
awk
будет считываться до тех пор, пока не будет закрыт записывающий конец канала. Обычно это происходит только тогда, когдаcmd
(и все процессы, которые он разветвляет и все еще удерживает fd для канала ), завершаются. Если по какой-то причине cmd
решит явным образом закрыть свой стандартный вывод, а затем записать еще какой-то прогресс в stderr, этот дополнительный прогресс может закончиться после нормального вывода. Вы можете обойти это, заменив cmd
на (cmd; exit)
, где awk
также будет ждать завершения этой подоболочки (, которая также имеет свой стандартный вывод, открытый для канала ), и эта подоболочка ожидает завершения cmd
, чтобы закончить (и сообщить о своем статусе выхода с помощьюexit
).
Но это не должно быть необходимо с хорошим -поведением cmd
. Это также не устранило бы случай, когда cmd
разветвляется (и не ожидает )дочернего процесса с перенаправленным стандартным выводом, который может писать в свой стандартный вывод задолго после awk
или даже после завершения этого сценария (. ] вероятно, более вероятный сценарий, чем команда, которая явно закрывает свой стандартный вывод ).
Если вывод cmd
не является текстом, обратите внимание, что не все реализации awk
могут работать с байтом 0 или дополнительными -длинными строками, и в конце будет добавлен символ новой строки, если он еще не был на входе.
В наборе инструментов POSIX нет команды, которая может хранить произвольное количество двоичных данных в памяти и отображать их позже.
Если доступно perl
, вы можете заменить команду awk
только командой perl -0777 -pe ''
.
Здесь вместо памяти вы можете сохранить выходные данные во временном файле, что решит проблему двоичного вывода и, вероятно, лучше масштабируется для больших выходных данных.
К сожалению,единственный надежный способ POSIX создать временный файл — это использовать утилиту m4
, но эта утилита (, хотя она и предусмотрена POSIX ), не всегда встречается в производственных системах в наши дни. Вероятно, у вас больше шансов найти perl
, чем m4
.
Во всяком случае, это может быть:
die() {
[ "$#" -eq 0 ] || printf >&2 '%s\n' "$@"
exit 1
}
tmpdir=${TMPDIR:-/tmp}
tmpfile=$(
echo 'mkstemp(TEMPLATE)' |
m4 -D "TEMPLATE=${tmpdir%/}/XXXXXXX"
) && [ -n "$tmpfile" ] || die 'Cannot get a temp file'
{
rm -f -- "$tmpfile" || die "Cannot remove $tmpfile"
cmd 2>&1 >&3 3>&- 4<&-
cat <&4
} 3> "$tmpfile" 4< "$tmpfile"
Здесь удаление связи с временным файлом после его открытия, но перед запуском cmd
в качестве удобного способа очистки -.
Если вы ориентируетесь только на GNU (, помните, что «Linux» — это не ОС, а просто ядро, встречающееся в большом количестве ОС, в некоторых из которых даже нетsh
)и систем OpenBSD, тогда вы должны иметь возможность использовать mktemp
вместо m4
для создания временного файла.