отрезать команду, заказ не сохранился?

У меня есть пример файла:

[root@localhost base_filters]# cat shortlist 2233|charles harris |gm |sales |12/12/52| 90000 9876|bill johnson |director |production|03/12/50|130000 5678|robert dylan |dgm |marketing |04/19/43| 85000 2365|john woodcock |director |personnel |05/11/47|120000 5423|barry wood |chairman |admin |08/30/56|160000 

Я хотел перевернуть имена в файле таким образом, чтобы после запятой была запятая , то есть, например, имя должно появиться как harris, charles.

Я попробовал следующую команду: –

 [root@localhost base_filters]# tr -s ' ' < shortlist | cut -d\| -f2 | cut -d' ' -f2,1 charles harris bill johnson robert dylan john woodcock barry wood 

Я хочу, чтобы фамилия появилась первой, поэтому я указал поле 2, а затем 1, но это, похоже, не работает. Любые идеи об этом?

Это легко сделать с помощью awk . Сначала распечатайте имя, затем снова подайте вывод на awk (на этот раз используя пространство в качестве разделителя файлов).

 awk -F "|" '{print $2}' extract.txt | awk -F " " '{print $2 "," $1}' 

Следующая функция будет использовать только встроенные модули Bash (в случае, если вы хотите использовать Bash), чтобы делать то, что вы хотите:

 foo () { local filename="$1" while IFS='|' read -r pre name suf; do l="$pre|${name#* },${name% *}|$suf"; printf '%s\n' "$l"; done < "$filename" } 

Для переменной IFS установлено значение | и «читать» читает каждую строку за раз от «$ 1» (ваш файл) и делит ее на три части: $ pre $ name и $ suf , согласно значению IFS.

$ pre value устанавливается как поле перед именем, $ name устанавливается как само имя, которое вы хотите поменять (второе поле) и $ suf – это остальная часть строки.

Я использую расширение параметра (также поиск расширения параметров в man bash ), чтобы разделить поле $ name .

"${name#* }" сократит имя, оставив нас с фамилией.

"${name% *}" сократит фамилию, оставив нам имя.

Использование: foo [/path/to/file.txt]

Пример вывода:

 nylon100@~$ cat>file.txt 123|first1 last1|foo|bar|date|baz 456|first2 last2|foo|bar|date|baz 789|first3 last3|foo|bar|date|baz nylon100@~$ foo file.txt 123|last1,first1|foo|bar|date|baz 456|last2,first2|foo|bar|date|baz 789|last3,first3|foo|bar|date|baz 

Да, cut не меняет порядок, он просто выбирает данные из каждой строки.

Вам нужно будет использовать sed или awk например:

 sed 's/^\([^|]*|\)\([^|]\{1,\}\) \([^ |]\{1,\}\)/\1\3,\2/' 

На странице man

Выбранный вход записывается в том же порядке, в котором он считывается, и записывается ровно один раз.

Поэтому вы должны использовать другой инструмент вместо сокращения. Например, sed, awk, perl, python или bash.

Пытаться:

 tr -s ' ' < shortlist | cut -d\| -f2 | tr '\n' ' ' | tac -s' ' | \ sed -e 's/^[[:space:]]//' -e 's/ /\n/g' | sort 

Или, если у вас много таких файлов:

 sortnames () { tr -s ' ' < $1 | cut -d\| -f2 | tr '\n' ' ' | tac -s' ' | \ sed -e 's/^[[:space:]]//' -e 's/ /\n/g' | sort } 

+1 все, за их поддержку :). Я нашел еще более простое решение:

 [root@localhost base_filters]# paste -d, <(cut -d\| -f2 shortlist| cut -d' ' -f2) <(cut -d\| -f2 shortlist| cut -d' ' -f1) harris,charles johnson,bill dylan,robert woodcock,john wood,barry