कैसे sed के साथ अनुगामी व्हाट्सएप को हटाने के लिए?


113

मेरे पास एक सरल शेल स्क्रिप्ट है जो एक फ़ाइल से ट्रेलिंग व्हाट्सएप को हटाती है। क्या इस स्क्रिप्ट को और अधिक कॉम्पैक्ट बनाने का कोई तरीका है (बिना अस्थायी फ़ाइल बनाए)?

sed 's/[ \t]*$//' $1 > $1__.tmp
cat $1__.tmp > $1
rm $1__.tmp

2
आप उपयोग कर सकते हैं mvके बजाय catऔर rm। तुम catवैसे भी क्यों इस्तेमाल कर रहे हो ? उपयोग क्यों नहीं cp?
अगली सूचना तक रोक दिया गया।

1
मैंने इस प्रश्न से जो ज्ञान सीखा, उसका उपयोग मैंने पुनरावृत्ति वाले व्हाट्सएप को हटाने के लिए एक शेल स्क्रिप्ट बनाने के लिए किया
डेविड टाइट

1
आपका समाधान वास्तव में बेहतर है जब विंडोज पर सीड में बग के कारण MinGW का उपयोग किया जाता है: stackoverflow.com/questions/14313318/…
Cody Piersall


ध्यान दें कि catमूल फ़ाइल को अधिलेखित करने के बजाय mvवास्तव में मूल फ़ाइल में डेटा को प्रतिस्थापित करेगा (यानी, यह हार्ड लिंक नहीं तोड़ देगा)। sed -iकई समाधानों में प्रस्तावित के रूप में उपयोग करना ऐसा नहीं होगा। IOW, बस वही करो जो आप कर रहे हैं।
विलियम पुरसेल

जवाबों:


157

आप लिनक्स और यूनिक्स के स्थान विकल्प -iका उपयोग कर सकते हैं sed:

sed -i 's/[ \t]*$//' "$1"

ध्यान रखें कि अभिव्यक्ति tOSX पर ट्रेलिंग को हटा देगी (आप gsedइस समस्या से बचने के लिए उपयोग कर सकते हैं )। यह उन्हें बीएसडी पर भी हटा सकता है।

यदि आपने नहीं लिया है, तो OSX पर सही (लेकिन पढ़ने में कठिन) sed सिंटैक्स है:

sed -i '' -E 's/[ '$'\t'']+$//' "$1"

तीन एकल-उद्धृत तार अंततः एक तर्क / अभिव्यक्ति में संक्षिप्त हो जाते हैं। बैश में कोई कॉन्टैक्शंस ऑपरेटर नहीं है, आप बस एक के बाद एक स्ट्रिंग्स को रखें, जिसके बीच में कोई जगह नहीं है।

$'\t'बैश में एक शाब्दिक टैब-चरित्र के रूप में हल (का उपयोग करते हुए एएनएसआई-सी के हवाले से ,) तो टैब सही ढंग से अभिव्यक्ति में concatenated है।


1
मुझे अपनी मशीन पर निम्नलिखित मिलेंगे जिन्हें मैं अपडेट नहीं कर सकता: sed: Not a recognized flag: i
javaPl4242

2
एचएम। यह भी इस अर्थ में छोटी गाड़ी है कि यह
गुड पर्सन

2
"sed: मान्यता प्राप्त ध्वज नहीं: i -" यह OSX पर होता है। आपको Mac पर बैकअप फ़ाइल -i के बाद एक्सटेंशन जोड़ने की आवश्यकता है। उदाहरण: sed -i .bak's / [\ t] * $ // '$ 1
Aimon Bustardo

1
@GoodPerson यदि आप मजाक नहीं कर रहे थे, तो आप बचने की भूल कर सकते हैं t:) \tएक टैब है, उन लोगों के लिए जो पहले से नहीं जानते होंगे।
सीन एलेड

2
@ सीन ऑयर्ड मजाक नहीं कर रहा था: इसका पूरी तरह से टूटना जब तक कि आप जीएनयू सेड का उपयोग नहीं करते (जो कि कई अन्य तरीकों से टूटा हुआ है)
गुड पर्सन

59

कम से कम माउंटेन लॉयन पर, विक्टर का जवाब चरित्र के 'टी' को भी हटा देगा जब यह एक पंक्ति के अंत में होगा। निम्न समस्याएँ हल करता है:

sed -i '' -e's/[[:space:]]*$//' "$1"

1
मेरी सीड भी एक -Eसंकेत "विस्तारित (आधुनिक) नियमित अभिव्यक्ति" चाहती थी
जेरेड बेक

OS X पर एक आकर्षण की तरह काम करता है। बहुत बहुत धन्यवाद।
jww

1
कोडडक्ट के जवाब में OS X (अब macOS) पर एक ही समस्या है। इस मंच पर यही एकमात्र समाधान है।
फ्रैंकलिन यू

sedएल Capitan पर @JaredBeck मेरा नहीं था।
फ्रैंकलिन यू

19

-iविकल्प सुझाने के लिए कोडेडडिक्ट का धन्यवाद ।

निम्न आदेश स्नो लेपर्ड पर समस्या हल करता है

sed -i '' -e's/[ \t]*$//' "$1"

मैंने इसे यहाँ पाया, joemaller.com/823/quick-note-about-rews-edit-in-place-option
विक्टर

7
जैसे @acrollet कहता है, आप \tGNU सेड के अलावा अन्य सेड के साथ उपयोग नहीं कर सकते हैं और इसे शाब्दिक अक्षर के रूप में समझा जाता है t। आदेश केवल काम करने के लिए प्रकट होता है, शायद क्योंकि अनुगामी व्हाट्सएप में कोई TAB नहीं हैं और न ही tआपकी फ़ाइल में एक वाक्य के अंत में। ''बैकअप प्रत्यय निर्दिष्ट किए बिना उपयोग करने की अनुशंसा नहीं की जाती है।
स्क्रूटिनीज़र


5
var1="\t\t Test String trimming   "
echo $var1
Var2=$(echo "${var1}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
echo $Var2

1
अरे, यह वही है जो मुझे चाहिए था! पोस्ट किए गए अन्य सेड सॉल्यूशंस ने मेरी बैश स्क्रिप्ट में एक पाइप्ड (और पाइप्ड एंड पाइप्ड ...) वेरिएबल असाइनमेंट के साथ इंटीग्रेट करने में समस्या थी, लेकिन आपका काम बॉक्स से बाहर हो गया।
एरिक एल।

4

मेरे पास मेरी .bashrc में एक स्क्रिप्ट है जो OSX और Linux (केवल बैश!) के तहत काम करती है।

function trim_trailing_space() {
  if [[ $# -eq 0 ]]; then
    echo "$FUNCNAME will trim (in place) trailing spaces in the given file (remove unwanted spaces at end of lines)"
    echo "Usage :"
    echo "$FUNCNAME file"
    return
  fi
  local file=$1
  unamestr=$(uname)
  if [[ $unamestr == 'Darwin' ]]; then
    #specific case for Mac OSX
    sed -E -i ''  's/[[:space:]]*$//' $file
  else
    sed -i  's/[[:space:]]*$//' $file
  fi
}

जिस पर मैं जोड़ता हूं:

SRC_FILES_EXTENSIONS="js|ts|cpp|c|h|hpp|php|py|sh|cs|sql|json|ini|xml|conf"

function find_source_files() {
  if [[ $# -eq 0 ]]; then
    echo "$FUNCNAME will list sources files (having extensions $SRC_FILES_EXTENSIONS)"
    echo "Usage :"
    echo "$FUNCNAME folder"
    return
  fi
  local folder=$1

  unamestr=$(uname)
  if [[ $unamestr == 'Darwin' ]]; then
    #specific case for Mac OSX
    find -E $folder -iregex '.*\.('$SRC_FILES_EXTENSIONS')'
  else
    #Rhahhh, lovely
    local extensions_escaped=$(echo $SRC_FILES_EXTENSIONS | sed s/\|/\\\\\|/g)
    #echo "extensions_escaped:$extensions_escaped"
    find $folder -iregex '.*\.\('$extensions_escaped'\)$'
  fi
}

function trim_trailing_space_all_source_files() {
  for f in $(find_source_files .); do trim_trailing_space $f;done
}

3

उन लोगों के लिए जो दक्षता की तलाश करते हैं (कई फाइलें संसाधित करने के लिए, या बड़ी फाइलें), +दोहराव ऑपरेटर का उपयोग करने के बजाय *कमांड को दो बार से अधिक तेज बनाता है।

GNU sed के साथ:

sed -Ei 's/[ \t]+$//' "$1"
sed -i 's/[ \t]\+$//' "$1"   # The same without extended regex

मैंने जल्दी से कुछ और भी बेंचमार्क किया: [ \t]इसके बजाय [[:space:]]इस प्रक्रिया को तेज करने के लिए उपयोग करना (GNU sed v4.4)

sed -Ei 's/[ \t]+$//' "$1"

real    0m0,335s
user    0m0,133s
sys 0m0,193s

sed -Ei 's/[[:space:]]+$//' "$1"

real    0m0,838s
user    0m0,630s
sys 0m0,207s

sed -Ei 's/[ \t]*$//' "$1"

real    0m0,882s
user    0m0,657s
sys 0m0,227s

sed -Ei 's/[[:space:]]*$//' "$1"

real    0m1,711s
user    0m1,423s
sys 0m0,283s

1

सिर्फ मनोरंजन के लिए:

#!/bin/bash

FILE=$1

if [[ -z $FILE ]]; then
   echo "You must pass a filename -- exiting" >&2
   exit 1
fi

if [[ ! -f $FILE ]]; then
   echo "There is not file '$FILE' here -- exiting" >&2
   exit 1
fi

BEFORE=`wc -c "$FILE" | cut --delimiter=' ' --fields=1`

# >>>>>>>>>>
sed -i.bak -e's/[ \t]*$//' "$FILE"
# <<<<<<<<<<

AFTER=`wc -c "$FILE" | cut --delimiter=' ' --fields=1`

if [[ $? != 0 ]]; then
   echo "Some error occurred" >&2
else
   echo "Filtered '$FILE' from $BEFORE characters to $AFTER characters"
fi

0

के विशिष्ट मामले में sed, जो -iविकल्प दूसरों ने पहले ही उल्लेख किया है वह सबसे सरल और पवित्र है।

अधिक सामान्य स्थिति में, sponge, से moreutilsयह आप एक तरह से विशेष रूप से अधिलेखित बहुत फाइल यह द्वारा पर ही ट्रिपिंग से प्रसंस्करण कदम रखने के लिए डिज़ाइन में इसे संसाधित करने का परिणाम के साथ एक फ़ाइल को बदलने, कर सकते हैं: संग्रह, वास्तव में आप क्या चाहते हैं करता है काम पर। spongeमैन पेज को उद्धृत करने के लिए :

स्पंज मानक इनपुट पढ़ता है और इसे निर्दिष्ट फ़ाइल पर लिखता है। शेल पुनर्निर्देशित के विपरीत, स्पंज आउटपुट फाइल लिखने से पहले अपने सभी इनपुट को भिगो देता है। यह उन पाइपलाइनों का निर्माण करने की अनुमति देता है जो उसी फ़ाइल से पढ़ते हैं और लिखते हैं।

https://joeyh.name/code/moreutils/


-1

कम से कम एक गैर-व्हाट्सएप चरित्र (इस तरह से खाली इंडेंटेड लाइनों को नहीं छुआ जाता है) के साथ लाइनों से केवल मेरे व्हाट्सएप (मेरे मामले में रिक्त स्थान और टैब) में।

sed -i -r 's/([^ \t]+)[ \t]+$/\1/' "$file"
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.