Предполагая строго разделенный таблицами вход:
$ cat data.in
a b c
A nancy bilbo baggins 0
B 0 darcy bender
C phantom menace Unix !!
D last row 0 the end
$ cat -t data.in
^Ia^Ib^Ic
A^Inancy^Ibilbo baggins^I0
B^I0^Idarcy^Ibender
C^Iphantom menace^IUnix^I!!
D^Ilast row^I0^Ithe end
Скрипт awk
для выполнения работы:
BEGIN { OFS = FS = "\t" }
NR != 1 {
for (i = 2; i <= NF; ++i) {
if ($i != "0") {
$i = "1";
}
}
}
{ print }
Запуск:
$ awk -f script.awk data.in
a b c
A 1 1 0
B 0 1 1
C 1 1 1
D 1 0 1
Скрипт сравнивает каждое поле (столбец) с единственным символом 0
(кроме первого поля) и заменяет все, что не точно 0
на 1
. Вывод будет разделен табуляцией.
Учитывая, что заголовки не содержат чисел, подобных вашему образцу, я могу придумать самый простой способ:
sed 's/[1-9]/1/g' file.txt
помните о диапазоне: от 1 до 9, без нуля.
$ echo "A 5 2 0" |sed 's/[1-9]/1/g'
A 1 1 0
Это работает, если числа в столбцах до 9. Если это не так, и числа могут быть 10 или более, я должен пересмотреть.
Согласно последним разъяснениям OP, поскольку ненулевые записи могут быть именами и т. Д., Это НЕ будет работать.
sed '1!s/ [^ ]*[^ 0][^ ]*/ 1/g'
Заменяет любую последовательность непробельных символов, содержащую хотя бы один символ, отличный от 0
(и следующий за пробелом), на 1
(кроме первой строки).
IOW, это заменит все, кроме последовательности нулей, первого столбца и строки на 1
.
Это хорошая задача для Python.
$ cat input.txt
a b c
A alpha beta 0
B 0 gamma zeta
C alpha phi omega
D kappa 0 delta
$ ./replace_nonzero.py < input.txt
a b c
A 1 1 0
B 0 1 1
C 1 1 1
D 1 0 1
А вот replace_nonzero.py
:
#!/usr/bin/env python
from __future__ import print_function
import sys
for index,line in enumerate(sys.stdin):
if index == 0 :
print(line.strip())
continue
words = line.strip().split()
print(words[0],end="\t")
new_line = []
for word in words[1:]:
if word.isdigit() and int(word) == 0:
new_line.append('0')
else:
new_line.append('1')
print("\t".join(new_line))
Это работает просто: мы пропускаем первую строку, так как это особый случай, и разбиваем все остальные строки на слова и исследуем те, которые начинаются с позиции 1. Логика здесь работает исходя из противоположного предположения. - если полученное слово является цифрой и равно нулю, то мы добавляем строку «0» в новый список (который представляет собой список слов в каждой строке), иначе - мы добавляем строку «1». Наконец, мы берем новый список и снова распечатываем его - с разделителями табуляции.
Это работает только в bash
bash$ paste <(cut -f1 file) <(cut -f2- file |
sed -r '1b; # if title line then skip to end
s#\t#\n#g # seperate line to multi-line
s#.*[^0].*#1#Mg # apply multi-line operation
s#\n#\t#g' ) # turn to one line
a b c
A 1 1 0
B 0 1 1
C 1 1 1
D 1 0 1