Один из способов с использованием функции split
:
awk 'FNR==NR{a[$1]=$6; next}
{split($0, b, ","); u=b[1]; if (u in a) {$0=$0","a[u]}}
1' file2 file1
Она сохраняет 6-е поле из file2
в a[1st field]
, затем для каждой строки file1
разбивает ее через запятую на массив b
и присваивает первый элемент b[1]
в u
. Если u
находится в a
, он добавляет запятую и a[u]
к строке. Заключительный 1
печатает каждую строку file1
независимо от того, была она изменена или нет.
Если вы не делаете перевод только, вы не можете безопасно читать и писать одновременно (и даже при переводе возможно, что файл окажется "наполовину переведенным", если программа завершится с ошибкой).
Похоже, вам действительно нужна какая-то комбинация tee
и sponge
. Вы можете использовать sponge
из moreutils для поглощения стандартного ввода и последующей записи его в файл. Вы можете использовать tee
для дублирования ввода на несколько выходов.
Конечный результат будет выглядеть примерно так:
command < filename | tee >(sponge filename)
>()
- это пример подстановки процесса. В этом случае >(имя файла губки)
заменяется на путь к FIFO, который идет на stdin губки
, куда пишет tee
. tee
также записывает свой вход в stdout независимо.
Вот пример. Видно, что вывод записывается и в stdout, и в файл.
$ echo 'foo bar' > file
$ sed 's/foo/qux/' < file | tee >(sponge file)
qux bar
$ cat file
qux bar
Оператор перенаправления для открытия файла в режиме чтения + записи без усечения - <>
во всех оболочках типа Борна (который соответствует open (file, O_RDWR | O_CREAT)
(хотя zsh
также выдает O_NOCTTY
) или fopen (file, "w +")
):
exec 3<> "$file"
открывает $ файл
в файловом дескрипторе 3 в режиме чтения + записи (без его усечения и создания, если он не существует).
Однако только ksh93
и zsh
имеют ищущие операторы. dd
может искать, но не назад. И обратите внимание, что никакая оболочка, кроме zsh
, не может иметь байтов NUL в своих переменных.
В zsh
:
zmodload zsh/system
exec 3<> $file
sysread -i 3 -c 2 var # a read() of 2 bytes
sysseek -u 3 0 # seek back to beginning
# or sysseek -u 3 -w current -2 # to seek back 2 bytes
syswrite -o 3 something-else
exec 3<&- # close
В ksh93
:
exec 3<> "$file"
var=$(dd bs=2 count=1 <&3 2>/dev/null; echo .)
var=${var%?}
exec 3<#((0)) # seek to beginning
# or exec 3<#((CUR-2)) # to seek back 2 bytes
print -ru3 something-else
В переносном режиме вы все равно можете открывать файл несколько раз для каждого желаемого смещения, например, здесь для чтения и записи 2 байта со смещением 2 (при условии, что это не байты со значением 0, если не используется zsh
):
var=$(dd bs=2 count=1 skip=1 < "$file"; echo .)
var=${var%?}
printf %s something-else | dd bs=2 seek=1 1<> "$file"
Или:
printf %s something-else | dd bs=2 seek=1 of="$file" conv=notrunc
Для чтения и записи в один и тот же файл, ksh93
имеет два других интересных оператора перенаправления:
tr 01 10 < file >; file
сохранит вывод tr
во временном файле, и если tr
успешно, переименуйте его в файл
( будьте осторожны, файл создается заново, поэтому, возможно, с другими разрешениями и владельцами).
tr -d 0 < file 1<>; file
То же, что и стандартный / Bourne tr -d 0
, за исключением того, что в случае успеха tr
файл
усекается, где tr
закончил писать. Вы можете использовать это для команд фильтрации, которые производят меньше результатов, чем они читают ввод, или, точнее, команд, которые не будут читать данные, которые они ранее записали.
А zsh
имеет форму замены процесса = (...)
, которую можно использовать как:
mv =(tr 01 10 < file) file
(с таким же эффектом и оговорками, как ksh93
: >;
). Или:
cp =(tr 01 10 < file) file
, который сохранит атрибуты файла
, но означает дополнительную копию.
Теперь, если вам нужно читать и писать с одного и того же смещения с использованием одного и того же файлового дескриптора, и ни zsh, ни ksh93 недоступны, вы всегда можете вернуться к perl
/ python
/ рубин
...
perl -e '
open F, "<>", "file" or die "open: $!";
read F, $var, 1;
seek F, 0, 0;
print F "something-else"'
Теперь, после перечитывания обновленной версии вашего вопроса, похоже, что ваш файл ведет себя больше как сокет или двунаправленный канал, а не как обычный файл с возможностью поиска.
В этом случае, это может быть просто вопрос:
socat - file:your-file
или:
(cat >&3 3>&- & cat <&3 3<&-) 3<> your-file
, чтобы передать данные из этого файла и в этот файл как прочитанные из / в стандартный ввод / вывод.
Обратите внимание, что каждый cat
читает / записывает в свою собственную копию файлового дескриптора 3, открытого оболочкой, но они используют одно и то же описание открытого файла , поэтому оно должно быть эквивалентным.