У меня есть несколько файлов .txt, которые выглядят так:
XXXXXXXXXXXXXX
NNNNNNNNNNNNNN
NNNNNNNNNNNNNN
NNNNNNNNNNNNN
NNNNNNNNNNNN
NNNNNNNNNNN
XXXXXXXXXXXXXX
XXXXXXXXXXXXX
XXXXXXXXXXXXX
XXXXXXXXXXXX
NNNNNNNNNNNNN
NNNNNNNNNNNN
NNNNNNNNNNNNNN
NNNNNNNNNNNNNN
Можно ли дать команду в bash, что все строки, начинающиеся с N, должны заканчиваться в конце файла , Поэтому я ожидаю что-то вроде этого:
XXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXX
NNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNN
.. и сделать это для всех файлов из одной папки.
Вы можете использовать это:
{
grep -v '^N' file.txt
grep '^N' file.txt
} > file.txt.temp
mv file.txt.temp file.txt
Это работает, сопоставляя все строки, которые не начинаются с 'N' (grep -v '^N'
), затем сопоставляя все строки, которые начинаются с 'N' (grep '^N'
), выводя во временный файл, затем заменяя оригинал временным файлом.
Тогда, если вы хотите использовать это для всех * .txt файлов в каталоге:
for f in *.txt; do
{
grep -v '^N' "$f"
grep '^N' "$f"
} > "$f".temp
mv "$f".temp "$f"
done
Вот несколько использований опций awk
Во-первых, версия KISS - использование нескольких временных файлов a
и b
:
for f in *.txt; do
awk '/^N/ {print > "b"; next} {print > "a"}' "$f"
cat a b > "$f"
done
Просто так...
То, что Вы действительно хотите сделать, является оперативным видом с пользовательским порядком сортировки (строки, запускающиеся с N
после всего остального, затем первоначальный заказ), например, в GNU awk
:
function mycmp(ia, a, ib, b) {
x = substr(a,1,1) == "N"
y = substr(b,1,1) == "N"
if (x && !y) return 1
else if (!x && y) return -1
else return ia - ib
}
{a[FNR] = $0}
ENDFILE {
for (i in a) print a[i]
}
Более новые версии gawk
обеспечьте оперативное расширение - заимствование ссылочной реализации от 16.7.4 Включающих Оперативных Редактирований Файла, мы можем соединить все это как сценарий простофили, Nsort.awk
скажите:
#!/usr/bin/gawk -f
@load "inplace"
function mycmp(ia, a, ib, b) {
x = substr(a,1,1) == "N"
y = substr(b,1,1) == "N"
if (x && !y) return 1
else if (!x && y) return -1
else return ia - ib
}
BEGIN {
inplace = 1
INPLACE_SUFFIX = ".bak"
PROCINFO["sorted_in"] = "mycmp"
}
BEGINFILE {
if (_inplace_filename != "")
inplace_end(_inplace_filename, INPLACE_SUFFIX)
if (inplace)
inplace_begin(_inplace_filename = FILENAME, INPLACE_SUFFIX)
else
_inplace_filename = ""
}
{a[FNR] = $0}
ENDFILE {
for (i in a) print a[i]
}
END {
if (_inplace_filename != "")
inplace_end(_inplace_filename, INPLACE_SUFFIX)
}
Сделайте это исполняемым файлом с chmod +x Nsort.awk
и выполненный это как
./Nsort.awk *.txt
awk -i inplace '/^N/{ printlast = printlast $0 RS ; next } { print $0 } ENDFILE { printf "%s",printlast ; printlast="" }' file1 file2 file3
-i inplace
заменять исходный файл переупорядоченным файлом.Внимание: Это перезапишет файлы, которые установлены только для чтения.N
, добавьте строку к буферу printlast
.printlast
, затем сбросьте его для следующего файла.a.txt b.txt c.txt
или *.txt
).Замена -i inplace
с -i inplace -v INPLACE_SUFFIX=".bak"
сохранять копию каждого исходного файла. В этом примере имена файлов резервной копии все закончатся в .bak
.
Если Ваша версия awk
не может отредактировать файлы на месте, и если Вы не хотите создавать временные файлы, затем можно передать вывод по каналу awk
через sponge
(от moreutils
пакет):
ls -1 *.txt | \
while read file
do
chmod +w "${file}"
awk '/^N/{ printlast = printlast $0 RS ; next } { print $0 } ENDFILE { printf "%s",printlast }' "${file}" | \
sponge "${file}"
done
Необходимо сделать входные файлы перезаписываемыми- chmod +w "${file}"
- для sponge
изменить их.