Я пробовал много способов, но все еще не могу достичь того, чего хочу. Извините, я все еще учусь.
Я хочу вот этого:
Файл A.txt
5844
6069
6303
6309
Файл B.txt
// some comment
// some explanation
100,5,3,8,,,
500,5,44,8,,,
//2500,5,2,8,,,
2121,5,2,8,,,
5535,5,4,6069,,,
5844,1,4,5844,,,
5900,5,2,8,,,
6069,5,4,8,,,
Я хочу изменить искомый номер из A.txt и закомментировать строку в B.txt. Иногда искомый номер может отображаться в другом столбце, поэтому он изменит только первый столбец.
Результат:
// some comment
// some explanation
100,5,3,8,,,
500,5,44,8,,,
2500,5,2,8,,,
2121,5,2,8,,,
5535,5,4,6069,,,
//5844,1,4,5844,,,
5900,5,2,8,,,
//6069,5,4,8,,,
Я пробовал, и иногда это было беспорядочно, и я также менял другой столбец. Тогда я использовал что-то вроде этого, это очень долго и нелегко модифицировать,
awk -F ',' '/^5844/ && $1="5844"{$1="//5844"}1' b.txt > c.txt; cp c.txt ba.txt; rm -rf b.txt; mv ba.txt b.txt
и иногда также удаляют разделитель «,».
Пожалуйста, помогите, большое спасибо.
решение1
$ awk -F , 'FNR==NR { data[$1]=1; next } $1 in data { $0 = "//" $0 }; 1' 'File A.txt' 'File B.txt'
500,5,4,8,,,
5535,5,4,6069,,,
2121,5,4,8,,,
//5844,5,4,5844,,,
//6069,5,4,8,,,
Что я делаю здесь, так это сначала считываю числа из File A.txt
как ключи в ассоциативном массиве data
. Затем я проверяю каждое первое поле из, File B.txt
чтобы увидеть, является ли оно ключом data
или нет. Если это так, я добавляю //
к текущей строке. Затем печатаются все строки, измененные или нет.
Тест FNR==NR
будет истинным только при чтении из первого файла в командной строке, и блок заканчивается на next
. Это означает, что первый блок выполняется только для первого файла, в то время как второй блок выполняется для второго файла, если первое поле является ключом в массиве data
.
В 1
конце активируется вывод и может быть заменено на { print }
.
Вышеуказанное будет толькодобавлять //
к строкам во вторых файлах, соответствующим номерам в первом файле. Такжеудалять //
из линийнетсопоставил (т.е. обработал ваш обновленный вопрос):
$ cat 'File B.txt'
// some comment
// some explanation
100,5,3,8,,,
500,5,44,8,,,
//2500,5,2,8,,,
2121,5,2,8,,,
5535,5,4,6069,,,
5844,1,4,5844,,,
5900,5,2,8,,,
6069,5,4,8,,,
$ awk -F , 'FNR==NR { data[$1]=1; next } FNR > 2 { if ($1 in data) $0 = "//" $0; else sub("^//","") }; 1' 'File A.txt' 'File B.txt'
// some comment
// some explanation
100,5,3,8,,,
500,5,44,8,,,
2500,5,2,8,,,
2121,5,2,8,,,
5535,5,4,6069,,,
//5844,1,4,5844,,,
5900,5,2,8,,,
//6069,5,4,8,,,
Команда awk
предполагает, что вы хотите передать первые две строки File B.txt
без изменений (это то, о чем FNR > 2
заботится тест). FNR > 2
Блок проверяет, является ли число ключом data
или нет, и если это так, строка закомментирована, но если нет, все //
в начале строки удаляется с помощью sub()
.
Вместо FNR > 2
вы могли бы использовать /^\/\/ /
для проверки комментария в верхней части файла. Это потребовало бы, чтобы все такие комментарии всегда начинались с , //
за которым следует пробел.
Специальные переменные NR
и FNR
содержат общее количество прочитанных строк ( NR
) и в текущем файле ( FNR
).
Запятые «исчезнут», если я изменю только первое поле с помощью , $1 = "//" $1
что переформирует запись, используя текущее значение OFS
(пробел по умолчанию). Вы можете предотвратить это, используя BEGIN { OFS=FS }
, который установит OFS
символ запятой (или любой другой символ, который вы используете -F
в командной строке).