- Convert specified column in a multi-line string into single comma-separated line
- Convert array type variable to string type with space delimiter
- column to row using "," as delimter
- 2 Answers 2
- You must log in to answer this question.
- Linked
- Related
- Hot Network Questions
- Subscribe to RSS
- Bash: преобразование столбца текста в строку
- 15 комментариев, оставьте свой
- Оставьте свой комментарий Отменить ответ
- Parse all column elements from a linux bash command output
Convert specified column in a multi-line string into single comma-separated line
I like solutions like this too but is the -e arg necessary here since there’s only the first command being used for sed? I believe cat data.txt | xargs | sed ‘s/ /, /g’ would work all the same. For example, echo -e «foo\nbar\nbazz» | xargs | sed ‘s/ /, /g’ outputs foo, bar, bazz.
cut -d' ' -f5 file | paste -d',' -s +12.0,+15.5,+9.0,+13.5
For each line in the file; chop off the first field and spaces following, chop off the remainder of the line following the second field and append to the hold space. Delete all lines except the last where we swap to the hold space and after deleting the introduced newline at the start, convert all newlines to , ‘s.
$ awk -v ORS=, '' data.txt | sed 's/,$//' +12.0,+15.5,+9.0,+13.5
$ cat data.txt | tr -s ' ' | cut -d ' ' -f 2 | tr '\n' ',' | sed 's/,$//' +12.0,+15.5,+9.0,+13.5
cheers, what about if the input to awk was through standard input (just put function | awk. in your example?
awk one liner
Format specifier «%s», should be added after printf to make it more robust i.e. to make it work with all kind of rows such as «foo %s».
which finds the string starting with + , followed by any string \S\+ , then convert new line characters into commas. This should be pretty quick for large files.
sedSelectNumbers='s".* \(+8*[.]3*\) .*"\1,"' sedClearLastComma='s"\(.*\),$"\1"' cat file.txt |sed "$sedSelectNumbers" |tr -d "\n" |sed "$sedClearLastComma"
the good thing is the easy part of deleting newline «\n» characters!
EDIT: another great way to join lines into a single line with sed is this: |sed ‘:a;N;$!ba;s/\n/ /g’ got from here.
A solution written in pure Bash:
#!/bin/bash sometext="something1: +12.0 (some unnecessary trailing data (this must go)) something2: +15.5 (some more unnecessary trailing data) something4: +9.0 (some other unnecessary data) something1: +13.5 (blah blah blah)" a=() while read -r a1 a2 a3; do # we can add some code here to check valid values or modify them a+=("$") done " # between parenthesis to modify IFS for the current statement only (IFS=',' ; printf '%s: %s\n' "Result" "$")
Don’t seen this simple solution with awk
fg@erwin ~ $ perl -ne 'push @l, (split(/\s+/))[1]; END < print join(",", @l) . "\n" >'
You can also do it with two sed calls:
$ cat file.txt something1: +12.0 (some unnecessary trailing data (this must go)) something2: +15.5 (some more unnecessary trailing data) something4: +9.0 (some other unnecessary data) something1: +13.5 (blah blah blah) $ sed 's/^[^:]*: *\([+0-9.]\+\) .*/\1/' file.txt | sed -e :a -e '$!N; s/\n/,/; ta' +12.0,+15.5,+9.0,+13.5
First sed call removes uninteresting data, and the second join all lines.
You can also print like this:
Just awk: using printf
bash-3.2$ cat sample.log something1: +12.0 (some unnecessary trailing data (this must go)) something2: +15.5 (some more unnecessary trailing data) something4: +9.0 (some other unnecessary data) something1: +13.5 (blah blah blah) bash-3.2$ awk ' < if($2 != "") < if(NR==1) < printf $2 >else < printf "," $2 >> >' sample.log +12.0,+15.5,+9.0,+13.5
Another Perl solution, similar to Dan Fego's awk:
perl -ane 'print "$F[1],"' file.txt | sed 's/,$/\n/'
-a tells perl to split the input line into the @F array, which is indexed starting at 0.
Well the hardest part probably is selecting the second "column" since I wouldn't know of an easy way to treat multiple spaces as one. For the rest it's easy. Use bash substitutions.
# cat bla.txt something1: +12.0 (some unnecessary trailing data (this must go)) something2: +15.5 (some more unnecessary trailing data) something4: +9.0 (some other unnecessary data) something1: +13.5 (blah blah blah) # cat bla.sh OLDIFS=$IFS IFS=$'\n' for i in $(cat bla.txt); do i=$(echo "$i" | awk '') u="$$i" done IFS=$OLDIFS echo "$u" # bash ./bla.sh +12.0, +15.5, +9.0, +13.5
Convert array type variable to string type with space delimiter
If the first character of IFS variable is a space (which it is by default), you can use the star index in double quotes.
#! /bin/bash arr[0]=2019-06-26 arr[1]=15:21:54 string="$" printf "'%s'" "$string"
Documented under Special Parameters:
When the expansion occurs within double quotes, it expands to a single word with the value of each parameter separated by the first character of the IFS special variable.
For completeness, while the "$" Korn syntax (extended from the Bourne "$*" special parameter) would also work in zsh, in zsh, you may want to use the j (for join) parameter expansion flag instead which allows you to use any arbitrary joining string and doesn't need to rely on a global parameter like $IFS :
Note that for "$" , ksh (both ksh93 and mksh) join on the first byte of $IFS instead of first character. That matters for multi-byte characters like:
$ ksh -c 'a=(foo bar); IFS="⇅"; echo "$"' foo�bar $ mksh -c 'a=(foo bar); IFS="⇅"; echo "$"' foo�bar $ mksh -o utf8-mode -c 'a=(foo bar); IFS="⇅"; echo "$"' foo�bar
(where that � is how my terminal emulator rendered the first byte (0xe2) of that ⇅ character which by itself doesn't form a valid character).
Other Korn-like shells with array support are OK:
$ bash -c 'a=(foo bar); IFS="⇅"; echo "$"' foo⇅bar $ zsh -c 'a=(foo bar); IFS="⇅"; echo "$"' foo⇅bar $ yash -c 'a=(foo bar); IFS="⇅"; echo "$"' foo⇅bar
column to row using "," as delimter
I have a list of objects in column (file_column.txt) and I want to transpose this objects in row using "," as delimiter in a new file (file_row.txt). Es.
file_column.txt: Art 14f adr a24 file_row.txt: Art,14f,adr,a24
2 Answers 2
You have to use the right delimiter (comma) with the -d parameter:
paste -sd, file Art,14f,adr,a24
You have carriage returns in the files. Run dos2unix on any input file. What you described is possibly the result of having ^M or \r , Windows line endings, at the end of your file lines.
#! /bin/bash while read line do string="$,$" done < file_column.txt echo $> file_row.txt
The while read construction is more portable as it uses only Bash syntax and the builtin read .
Paste is a POSIX tool, Bash is not, so the portability claim is not true (although that script does not contain any bashism). Also see Why is using a shell loop to process text considered bad practice?.
Hey, no intention to destroy, only to constructively criticize 😉 And I guess we have all been there as well!
You must log in to answer this question.
Linked
Related
Hot Network Questions
Subscribe to RSS
To subscribe to this RSS feed, copy and paste this URL into your RSS reader.
Site design / logo © 2023 Stack Exchange Inc; user contributions licensed under CC BY-SA . rev 2023.7.12.43529
Linux is a registered trademark of Linus Torvalds. UNIX is a registered trademark of The Open Group.
This site is not affiliated with Linus Torvalds or The Open Group in any way.
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.
Bash: преобразование столбца текста в строку
Предположим, у нас есть текстовый файл с именем дистрибутивы.txt со следующим:
Archlinux
Debian
Ubuntu
Kaos
мягкая фетровая шляпа
Slackware
папуасских
И мы хотим превратить это в:
Archlinux, Debian, Ubuntu, Каос, Fedora, Slackware, Gentoo
Для этого мы будем использовать для цикла y un эхо -n :
Это покажет нам желаемый результат в терминале, если, с другой стороны, мы хотим, чтобы он был сохранен в другом файле .txt, мы перенаправляем вывод:
Ну ничего, надеюсь, вы сочтете это полезным. Действительно, чтобы уточнить, что это также можно сделать с помощью регулярных выражений, я просто не знаю, как . но с помощью регулярных выражений вы можете делать почти все, хахаха.
Содержание статьи соответствует нашим принципам редакционная этика. Чтобы сообщить об ошибке, нажмите здесь.
Полный путь к статье: Из Linux » Учебники / Руководства / Советы » Bash: преобразование столбца текста в строку
15 комментариев, оставьте свой
Оставьте свой комментарий Отменить ответ
Если в .odt у меня есть 2 столбца на каждой странице, они читаются так: стр.1
столбец 1 столбец 2
стр.2
столбец 3 столбец 4
и так далее Как мне расположить каждый столбец ниже другого?
столбец 1
столбец 2
столбец 3
столбец 4
и так далее
Намного легче: Если вы хотите разделить табуляцией:
Вы пишете: paste -s distros.txt
Вы получаете: archlinux debian ubuntu kaos fedora slackware gentoo Если вы хотите, чтобы он был разделен пробелами:
Вы пишете: paste -s -d »» distros.txt
Вы получаете: archlinux debian ubuntu kaos fedora slackware gentoo Если вы хотите разделить его запятыми:
Вы пишете: paste -s -d, distros.txt
Вы получаете: archlinux, debian, ubuntu, kaos, fedora, slackware, gentoo С paste, cat, awk и другими друзьями, проявив немного изобретательности, вы можете составить множество полезных комбинаций, не усложняя себе жизнь. Пусть все будет отлично, поздравляем с наградой в Portalprogramas!
Я использовал sed, awk, cut, sort, uniq, короче крем, но никогда не обращал внимания на paste, спасибо за то, что показал, на что он способен. Slds.
Parse all column elements from a linux bash command output
OR to make it print multiple columns using a colon delimited list:
awk -v col='2:7' ' BEGIN n < for (i=1; i in arr; ++i) printf "%s%s", $arr[i], (i < n ? OFS : ORS) >' file
With bash you can use 'read -a', this reads a line from standard input, splits using IFS field separator which has space by default and populates array variable which can be referenced as $ (zero based).
while read -a arr; do echo "$" echo "$" done
Unfortunately lsscsi does not provide consistent parseable output nor the chance to change the field separator as far as I see. With two different harddisks on the same system the column for the device is differing by one! The following code sniplet should give you an idea about what I mean and how I worked around it. at least to get the device which is at the end of the line. To get the product name and the product revision correctly, it could also be an idea to call each device with lssci -c a:b:c:d and then parse this output.
lsscsi > /tmp/tmp$$.out while read line do echo $line echo 012345678901234567890123456789012345678901234567890123456789 echo 0. 1. 2. 3. 4. 5. $line | cut -c2) TYPE=$(echo $line | cut -c16-18) PRODUCT=$(echo $line | sed -n 's/.\\(.*\) *\/dev\/.*/\1/p') DEVICE=$(echo $line | sed -n 's/.\.*\/dev\/\(.*\)/\1/p') echo $ID-$TYPE-$DEVICE-$PRODUCT done
Another easy way to do it without awk :
lsscsi | tr -s ' ' | cut -d' ' -f7
The last flag specifies the column.
Tested it again on a Linux machine and it works fine. My lsscsi output only has four columns, and therefore I use -f4 for the final argument. All output is treated as text in the shell, and in this case, we force separation by single space.