Переупорядочить столбцы с помощью разреза

У меня есть файл в следующем формате

Column1    Column2
str1       1
str2       2
str3       3

Я хочу, чтобы столбцы были перегруппированы. Я попытался выполнить команду

cut -f2,1 file.txt

Команда не изменяет порядок столбцов. Любая идея, почему он не работает?

Спасибо.

Ответ 1

Для справочной страницы cut(1):

Используйте один и только один из -b, -c или -f. Каждый СПИСОК состоит из один        диапазон или многие диапазоны, разделенные запятыми. Выбранный ввод написан        в том же порядке, что и считывается, и записывается ровно один раз.

Сначала он принимает поле 1, поэтому печатается, а затем поле 2.

Вместо этого используйте awk:

awk '{ print $2 " " $1}' file.txt

Ответ 2

Вы также можете комбинировать cut и paste:

paste <(cut -f2 file.txt) <(cut -f1 file.txt)

через комментарии: можно избежать ошибок и удалить один экземпляр среза, выполнив:

paste file.txt file.txt | cut -f2,3

Ответ 3

используя только оболочку,

while read -r col1 col2
do
  echo $col2 $col1
done <"file"

Ответ 4

Вы можете использовать Perl для этого:

perl -ane 'print "$F[1] $F[0]\n"' < file.txt
  • -e опция означает выполнение команды после нее
  • -n означает чтение строки за строкой (откройте файл, в этом случае STDOUT и переверните строки)
  • -a означает разделение таких строк на вектор, называемый @F ( "F" - подобное поле). Perl индексы векторов, начиная с 0, в отличие от разреза, который индексирует поля, начинающиеся с формы 1.
  • Вы можете добавить шаблон -F (без пробела между -F и pattern) для использования шаблона в качестве разделителя полей при чтении файла вместо стандартного пробела.

Преимущество работы perl в том, что (если вы знаете Perl), вы можете сделать гораздо больше вычислений на F, чем переупорядочивать столбцы.

Ответ 5

Просто работал над чем-то очень похожим, я не эксперт, но я думал, что буду делиться командами, которые я использовал. У меня было много столбцов csv, из которых мне требовалось только 4 столбца, а затем мне нужно было их переупорядочить.

Мой файл был pipe '|' но это может быть заменено.

LC_ALL=C cut -d$'|' -f1,2,3,8,10 ./file/location.txt | sed -E "s/(.*)\|(.*)\|(.*)\|(.*)\|(.*)/\3\|\5\|\1\|\2\|\4/" > ./newcsv.csv

По общему признанию, это действительно грубо и готово, но оно может быть изменено в соответствии с требованиями!

Ответ 6

Используя join:

join -t $'\t' -o 1.2,1.1 file.txt file.txt

Заметки:

  • -t $'\t' В GNU join к более интуитивно понятному -t '\t' без $ fails (coreutils v8.28 и более ранние?); это, вероятно, ошибка, что обходной путь, такой как $ должен быть необходим. Смотрите: unix join разделитель char.

  • join требуется два имени файла, хотя над ним работает только один файл. Используя то же имя дважды фокусы join в выполнение желаемого действия.

  • Для систем с ограниченными ресурсами join предлагает меньшую площадь, чем некоторые инструменты, используемые в других ответах:

    wc -c $(realpath 'which cut join sed awk perl') | head -n -1
      43224 /usr/bin/cut
      47320 /usr/bin/join
     109840 /bin/sed
     658072 /usr/bin/gawk
    2093624 /usr/bin/perl
    

Ответ 7

Я разместил другое решение под этим вопросом, используя короткий Python script, который гораздо удобнее использовать со многими столбцами: fooobar.com/info/63154/...