Hvordan trimmer jeg ledende og efterfølgende mellemrum fra hver linje med noget output?

Jeg vil gerne fjerne alle ledende og bageste mellemrum og faner fra hver linje i en output.

Er der et simpelt værktøj som trim Jeg kunne pibe min output til?

Eksempel på fil:

test space at back test space at front TAB at end TAB at front sequence of some space in the middle some empty lines with differing TABS and spaces: test space at both ends 

Kommentarer

  • Til alle, der søger her efter en løsning til at fjerne nye linjer, er det et andet problem. Per definition opretter en ny linje en ny tekstlinje. Derfor kan en tekstlinje ikke indeholde en ny linje. Det spørgsmål, du vil stille, er, hvordan du fjerner en ny linje fra begyndelsen eller slutningen af en streng: stackoverflow.com/questions/369758 , eller hvordan du fjerner tomt linjer eller linjer, der kun er mellemrum: serverfault.com/questions/252921

Svar

awk "{$1=$1;print}" 

eller kortere:

awk "{$1=$1};1" 

Vil trimme førende og efterfølgende mellemrum eller tabulatortegn 1 og også klem sekvenser af faner og mellemrum i et enkelt mellemrum.

Det fungerer, fordi når du tildeler noget til et af felterne , genopbygger awk hele posten (som udskrevet af print) ved sammenføjning af alle felter ($1, …, $NF) med OFS (mellemrum som standard).

1 (og muligvis andet tomt tegn s afhængigt af lokalitet og awk implementering)

Kommentarer

  • Semikolon til andet eksempel er overflødigt. Kunne bruge: awk '{$1=$1}1'
  • @Brian, nej, ; kræves i standard awk-syntaksen
  • Interessant … Intet semikolon understøttes af gawk, mawk og OS X ‘ s awk. (I det mindste for mine versioner (henholdsvis 1.2, 4.1.1 og 20070501)
  • Det eneste, jeg ikke ‘ kan lide ved denne tilgang er, at du mister gentagne mellemrum inden for linjen. F.eks. echo -e 'foo \t bar' | awk '{$1=$1};1'
  • echo ' hello ' | xargs

Svar

Kommandoen kan kondenseres som hvis du “bruger GNU sed:

$ sed "s/^[ \t]*//;s/[ \t]*$//" < file 

Eksempel

Her er ovenstående kommando i aktion.

$ echo -e " \t blahblah \t " | sed "s/^[ \t]*//;s/[ \t]*$//" blahblah 

Du kan bruge hexdump til at bekræfte, at kommandoen sed fjerner de ønskede tegn korrekt.

$ echo -e " \t blahblah \t " | sed "s/^[ \t]*//;s/[ \t]*$//" | hexdump -C 00000000 62 6c 61 68 62 6c 61 68 0a |blahblah.| 00000009 

Tegnklasser

Du kan også bruge tegnklassenavne i stedet for bogstaveligt at angive sætene som denne, [ \t]:

$ sed "s/^[[:blank:]]*//;s/[[:blank:]]*$//" < file 

Eksempel

$ echo -e " \t blahblah \t " | sed "s/^[[:blank:]]*//;s/[[:blank:]]*$//" 

De fleste af GNU-værktøjerne, der bruger regelmæssig ekspre ssions (regex) understøtter disse klasser (her med deres ækvivalenter i den typiske C-lokalitet for et ASCII-baseret system (og kun der)).

 [[:alnum:]] - [A-Za-z0-9] Alphanumeric characters [[:alpha:]] - [A-Za-z] Alphabetic characters [[:blank:]] - [ \t] Space or tab characters only [[:cntrl:]] - [\x00-\x1F\x7F] Control characters [[:digit:]] - [0-9] Numeric characters [[:graph:]] - [!-~] Printable and visible characters [[:lower:]] - [a-z] Lower-case alphabetic characters [[:print:]] - [ -~] Printable (non-Control) characters [[:punct:]] - [!-/:-@[-`{-~] Punctuation characters [[:space:]] - [ \t\v\f\n\r] All whitespace chars [[:upper:]] - [A-Z] Upper-case alphabetic characters [[:xdigit:]] - [0-9a-fA-F] Hexadecimal digit characters 

Brug disse i stedet for bogstavelige sæt virker altid som spild af plads, men hvis du er bekymret for, at din kode er bærbar eller har at gøre med alternative tegnsæt (tænk international), vil du sandsynligvis bruge klassens navne i stedet .

Referencer

Kommentarer

  • Bemærk, at [[:space:]] ikke svarer til [ \t] i almindelig sag (unicode osv.). [[:space:]] vil sandsynligvis være meget langsommere (da der er mange flere typer hvide rum i unicode end bare ' ' og '\t'). Samme ting for alle de andre.
  • sed 's/^[ \t]*//' er ikke bærbar. Til sidst kræver POSIX endda, at for at fjerne en sekvens af mellemrum, tilbageslag eller t tegn, og at ‘ er hvad GNU sed gør det også, når POSIXLY_CORRECT er i miljøet.
  • Hvad hvis jeg vil beskære nye linjer? ‘ \ n \ n tekst \ n \ n ‘
  • Jeg kan godt lide sed-løsningen på grund af manglen på andre bivirkninger som i awk-løsningen. Den første variation fungerer ikke, da jeg prøvede det i bash på OSX jsut nu, men tegnklasseversionen fungerer: sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//'
  • @EugeneBiryukov se min kommentar til det oprindelige indlæg

Svar

xargs uden argumenter gør det.

Eksempel:

trimmed_string=$(echo "no_trimmed_string" | xargs) 

Kommentarer

  • Dette kontraherer også flere mellemrum inden for en linje, som ikke blev anmodet om i spørgsmålet
  • @roaima – sandt, men det accepterede svar klemmer også mellemrum (hvilket ikke blev anmodet om i spørgsmålet). Jeg tror, at det virkelige problem her er, at xargs ikke leverer, hvis inputet indeholder tilbageslag og enkelt citater.
  • @don_crissti, der ikke ‘ t betyder, at det accepterede svar svarer korrekt på spørgsmålet, som det er stillet. Men i dette tilfælde blev det ikke ‘ t markeret som en advarsel, mens det i det accepterede svar var det. Jeg ‘ har forhåbentlig fremhævet det faktum, hvis det ‘ er relevant for en fremtidig læser.
  • Det er også bryder på enkelt anførselstegn, dobbelt anførselstegn, omvendt skråstreg tegn. Det kører også en eller flere echo påkaldelser. Nogle ekkoimplementeringer behandler også valgmuligheder og / eller tilbageslag … Det fungerer også kun for input med en linje.

Svar

Som foreslået af Stéphane Chazelas i det accepterede svar, kan du nu
oprette et script /usr/local/bin/trim:

#!/bin/bash awk "{$1=$1};1" 

og give den fil eksekverbare rettigheder:

chmod +x /usr/local/bin/trim 

Nu kan du sende alle output til trim for eksempel:

cat file | trim 

(til kommentarerne nedenfor: Jeg brugte dette før: while read i; do echo "$i"; done
som også fungerer fint, men er mindre performant)

Kommentarer

  • Held og lykke hvis din fil er enorm og / eller indeholder tilbageslag.
  • @don_crissti: kunne du kommentere lidt mere ?, hvilken løsning ville være bedre egnet til store filer, og hvordan kunne jeg ændre min løsning, hvis filen indeholdt tilbageslag?
  • Du ‘ skal bruge while read -r line til at bevare tilbageslag og selv da … . Med hensyn til enorme filer / hastighed valgte du virkelig den værste løsning. Jeg tror ikke ‘ der ‘ er noget værre derude. Se svarene på Hvorfor bruger en shell-løkke til at behandle tekst dårlig praksis? inklusive min kommentar til det sidste svar, hvor jeg tilføjede et link til en speed benchmark. sed svarene her er helt fine IMO og langt bedre end read.
  • Du kan også tilføje et alias i / etc / profil (eller din ~ / .bashrc eller ~ / .zshrc osv …) alias trim = ” awk ‘ { \ $ 1 = \ $ 1}; 1 ‘ ”
  • Intet behov for bash, du kan gøre det #! /usr/bin/awk -f {$1=$1};1. (pas på filnavne, der indeholder = tegn dog)

Svar

Hvis du gemmer linjer som variabler, kan du bruge bash til at udføre jobbet:

fjern ledende hvidt område fra en streng:

shopt -s extglob echo ${text##+([[:space:]])} 

fjern efterfølgende mellemrum fra en streng:

shopt -s extglob echo ${text%%+([[:space:]])} 

fjern alt hvidt mellemrum fra en streng:

echo ${text//[[:space:]]} 

Kommentarer

  • Fjernelse af al hvid plads fra en streng er ikke det samme som at fjerne både ledende og bageste mellemrum (som det er tale om).
  • Den bedste løsning – det kræver kun bash-indbyggede og ingen eksterne procesgafler.
  • Dejligt. Scripts kører MEGET hurtigere, hvis de ikke ‘ ikke behøver at trække i eksterne programmer (såsom awk eller sed). Dette fungerer også med ” moderne ” (93u +) versioner af ksh.

Svar

sed -e "s/^[[:space:]]*//" -e "s/[[:space:]]*$//" 

Hvis du læser en linje i en shellvariabel, read gør det allerede medmindre andet er instrueret .

Kommentarer

  • +1 for read. Så hvis du rører til, mens du læser det, fungerer det: cat file | while read i; do echo $i; done
  • @rubo bortset fra at i dit eksempel behandles den ikke-citerede variabel også af skallen. Brug echo "$i" for at se den virkelige effekt af read

Svar

For at fjerne alle ledende og bageste mellemrum fra en given linje takket være et “piped” værktøj kan jeg identificere 3 forskellige måder, der ikke er helt ækvivalente. Disse forskelle vedrører mellemrummene mellem inputlinjens ord. Afhængig af det forventede b ehaviour, du vælger.

Eksempler

For at forklare forskellene skal vi overveje denne dummy inputlinje:

" \t A \tB\tC \t " 

tr

$ echo -e " \t A \tB\tC \t " | tr -d "[:blank:]" ABC 

tr er virkelig en simpel kommando. I dette tilfælde sletter det ethvert mellemrum eller tabuleringstegn.

awk

$ echo -e " \t A \tB\tC \t " | awk "{$1=$1};1" A B C 

awk sletter ledende og hale mellemrum og klemmer til et enkelt mellemrum hvert mellemrum mellem ord.

sed

$ echo -e " \t A \tB\tC \t " | sed "s/^[ \t]*//;s/[ \t]*$//" A B C 

I dette tilfælde sed sletter ledende og haler mellemrum uden at røre mellemrum mellem ord.

Bemærk:

I tilfælde af et ord pr. linje udfører tr jobbet.

Kommentarer

  • Intet af dette trimmer efterfølgende / førende nye linjer dog
  • +1 for en liste over løsninger med deres (undertiden uventede) output.
  • @ user61382 dette er ret sent, men se min kommentar til det oprindelige indlæg.
  • @highmaintenance: brug [:space:] i stedet for [: blank:] til kommandoen tr, ligesom: ... | tr -d [:space:], for også at fjerne nye linjer. (se: man tr)

Svar

sed er en godt værktøj til det:

 # substitute ("s/") sed "s/^[[:blank:]]*//; # parts of lines that start ("^") with a space/tab s/[[:blank:]]*$//" # or end ("$") with a space/tab # with nothing (/) 

Du kan bruge det til din sag, enten rør i teksten, f.eks.

<file sed -e "s/^[[... 

eller ved at handle på den “inline”, hvis din sed er GNU-en:

sed -i "s/..." file 

men at ændre kilden på denne måde er “farlig”, da det kan være uopretteligt, når det ikke fungerer rigtigt (eller endda når det gør det!), så sikkerhedskopier først (eller brug -i.bak som også har fordelen ved at være bærbar til nogle BSD sed s)!

Svar

Et svar, du hurtigt kan forstå:

#!/usr/bin/env python3 import sys for line in sys.stdin: print(line.strip()) 

Bonus: erstatt str.strip([chars]) med vilkårlige tegn til at trimme eller bruge .lstrip() eller .rstrip() efter behov.

Ligesom rubo77 “sa nswer , gem som script /usr/local/bin/trim og giv tilladelser med chmod +x.

Svar

Hvis den streng, man prøver at trimme, er kort og kontinuerlig / sammenhængende, kan man blot sende den som en parameter til enhver bash-funktion:

 trim(){ echo $@ } a=" some random string " echo ">>`trim $a`<<" Output >>some random string<< 

Svar

Jeg skrev denne shell-funktion ved hjælp af awk

awkcliptor(){ awk -e "BEGIN{ RS="^$" } {gsub(/^[\n\t ]*|[\n\t ]*$/,"");print ;exit}" "$1" ; } 

BEGIN{ RS="^$" }:
i starten før parsering start sæt rekord og separator til ingen dvs. behandle hele input som
en enkelt post

gsub(this,that):
erstatte denne regexp med den streng

/^[\n\t ]*|[\n\t ]*$/:
af denne streng fanger et hvilket som helst præ-newline-område og faneklasse
eller post newline-space og faneklasse og udskift dem med en tom streng

print;exit: Udskriv og afslut derefter

"$1":
og send det første argument for funktionen til være
proces ved awk

hvordan man bruger:
kopiere ovenstående kode, indsæt i shell, og indtast derefter for at definere funktionen.
så kan du bruge awkcliptor som en kommando med det første argument som inputfil

eksempelbrug:

echo " ggggg " > a_file awkcliptor a_file 

output:

ggggg 

eller

echo -e "\n ggggg \n\n "|awkcliptor 

output:

ggggg 

Kommentarer

  • Kan du venligst forklare forskellen til awk '{$1=$1};1'?

Svar

For de af os uden plads nok i hjernen til at huske uklar sed syntaks skal du bare vende strengen , klip det første felt med en afgrænsning af mellemrum, og vend det tilbage igen.

cat file | rev | cut -d" " -f1 | rev 

Kommentarer

  • Dette fungerer kun, hvis der ikke er mere end et mellemrum, der fører hver linje og ikke mere end et ord i en hvilken som helst linje.

Svar

trimpy () { python3 -c "import sys for line in sys.stdin: print(line.strip())" } trimsed () { gsed -e "s/^[[:space:]]*//" -e "s/[[:space:]]*$//" } trimzsh () { local out="$(</dev/stdin)" [[ "$out" =~ "^\s*(.*\S)\s*$" ]] && out="$match[1]" || out="" print -nr -- "$out" } # example usage echo " hi " | trimpy 

Bonus: udskift str.strip([chars]) med vilkårlige tegn til at trimme eller brug eller .rstrip() efter behov.

Svar

translate-kommando fungerer

cat file | tr -d [:blank:] 

Kommentarer

  • Denne kommando er ikke korrekt, da den fjerner alle mellemrum fra filen, ikke kun ledende / efterfølgende mellemrum.
  • @BrianRedbeard Du har ret. Dette er stadig et nyttigt svar til en monolitisk streng uden mellemrum.

Svar

til bash-eksempel:

alias trim="awk "{\$1=\$1};1"" 

brug:

echo -e " hello\t\tkitty " | trim | hexdump -C 

resultat:

00000000 68 65 6c 6c 6f 20 6b 69 74 74 79 0a |hello kitty.| 0000000c 

Kommentarer

  • awk '{$1=$1};1' svaret blev givet for længe siden. Ideen om at lave et alias ud af det blev foreslået i en kommentar næsten lige så længe siden. Ja, du har lov til at tage en andens kommentar og gøre det til et svar. Men hvis du gør det, skal du give kredit til de mennesker, der sendte ideen foran dig. Og dette er sådan en triviel udvidelse af det accepterede svar, at det ikke rigtig er det værd at gøre.
  • Idéen var at lave alias. Jeg så ‘ ikke svaret før.
  • og anden ting fra stack: ” Tak for feedbacken! Stemmer, der afgives af dem, der har mindre end 15 omdømme, registreres, men ændrer ikke den offentlig viste stilling. ”

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *