⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 search.py

📁 convert C programs for use in C++ compiler environment
💻 PY
字号:
#! /usr/bin/env python

# Search and Replace by D.G. Sureau  - 1  May 2000 - (c) 2000-2004
# Freeware

# This program searches and (optionaly) replaces
# a string in a file, or in a set of files matching
# a pattern.
# The pattern may contain wilcards which are those
# of MS-DOS and Unix: * and ?
# Unlike fixcid, the script included in the Python
# distribution, it doesn't use regular expressions.
# The search can be performed case-sensitive or not.
# One can search identifiers in C or Python source,
# or any string in any pure ASCII text.

# By changing the "delimiters" string, you may
# specify what is identifier. The current setting
# doesn't include "#" among delimiters.

"""
    C to C++ Translator
    Copyright (C) 2000-2004  D.G Sureau

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    webmaster@scriptol.org
    http://www.scriptol.org

"""


import sys
import os
import os.path
import string

#------------------- Globals

FALSE = 0
TRUE  = 1
VERSION = "1.1.0"

delimiters = " \\.()[]{},;:?+-*=/&~|\"\'<>!\r\n\t"

counter = 0

#---------------- This function displays the command line syntax

def syntax():
 prog = sys.argv[0]
 print "Search and replace  - Freeware - www.scriptet.com"
 print 'Syntax:   ' + prog + ' [option] search-string [replacing-string] file'
 print '    or:   ' + prog + ' [option] search-string [replacing-string] pattern'
 print 'Options:'
 print '  -i   ignore case for strings (default case-sensitive)'
 print '  -c   search for identifiers (default strings)'
 print '  -w   Windows mode, ignore case for filenames (default case-sensitive)'
 print '  -q   quiet, don\'t display matches (default display)'
 print '  -v   version'
 print '  -h   help'
 print '  -icwq is the format for multiple options'
 sys.exit(0)

def version():
  print VERSION
  sys.exit()

#--------------------- Comparing a pattern and a filename

# Comparing two strings, first with wildcards

def matchingstr(str1, str2, casesensitive):

  if str1 == '*': return TRUE
  if len(str1) <> len(str2): return FALSE

  #Now comparing each char, but the ? wildcard
  i = 0
  for c in str1:
   if c == '?': continue
   if casesensitive == TRUE:
      if c <> str2[i]: return FALSE
   else:
      if(string.upper(c) <> string.upper(str2[i])): return FALSE
   i = i + 1

  return TRUE


# Comparing two filenames with wildcards

def matching(pattern, filename, casesensitive):

 #Extracting node and last extension
 namep, extp = os.path.splitext(pattern)
 namef, extf = os.path.splitext(filename)

 if not matchingstr(namep, namef, casesensitive): return FALSE
 if not matchingstr(extp, extf, casesensitive): return FALSE
 return TRUE



#------------------------------------- Split words

# This function make a list of words from both
# delimited identifiers and sequence of delimiters
# to allow the whole line rebuilt with replacements

def split(str):
 words = []
 newword = ""
 delimseq = ""

 for c in str:
  if string.find(delimiters, c) != -1:      # char in delimiter list
   if newword != "": words.append(newword)  # then word ended, add it
   newword = ""                             # clear it
   delimseq = delimseq + c                  # add delimiter to sequence
  else:                                      # else char in a word
   if delimseq != "": words.append(delimseq) # then delim seq ended, add it
   delimseq = ""                             # clear it
   newword = newword + c                     # add char to word

 # End of string, either a word or a delimiter sequence remains here
 if newword != "": words.append(newword)
 if delimseq != "": words.append(delimseq)
 return words


#------------------------------------ Join words & delimiters

def join(wordlist):
 str = ""
 for w in wordlist: str = str + w
 return str


# ----------------------------------- Replace words in string
# - as API's string.replace, but case-sensitive or no,
# - and count occurences

def replace(line, searching, replacing, TEXTCASE):

 global counter

 sealen = len(searching)
 replen = len(replacing)
 linelen = len(line)

 if TEXTCASE == FALSE:               # Ignore case
  searching  = string.lower(searching)
  line = string.lower(line)

 idx = 0
 idr = 0

 while((idx + sealen) < linelen):
  idx = string.find(line, searching, idx)    # Is "searching" inside line?
  if idx == -1: break                        # No more occurence, exit
  line = line[0:idx] + replacing + line[idx+sealen:]  # Replacing
  idx = idx + replen                         # Skipping scanned part of iline
  linelen = len(line)
  counter = counter + 1

 return line


#------------------------------------- Open a file

def openfile(filename, mode):
  try:
   f = open(filename, mode)
   return f
  except:
   print "Enable to open ", filename
   return None

def openread(filename):  return openfile(filename, 'r')

# Opened as binary to eliminate any line terminator
def openwrite(filename): return openfile(filename, 'wb')


#------------------------------------------ Replaces a file
#- Makes it ".bak" and renames a temporary file to its name

# Parameters are previous and temporary filenames

def replacefile(srcname, dstname):  

 # If source filename is node.ext it becomes node.bak
 # but if node itself is the name of an existing file,
 # source file will be renamed rather node.ext.bak

 node, ext = os.path.splitext(srcname)
 if os.path.exists(node):
  if ext != "":
   node = srcname

 newname = node + ".bak"
 if os.path.exists(newname): os.remove(newname)

 os.rename(srcname, newname)   # Previous renamed as .bak
 os.rename(dstname, srcname)   # Temporary gets name of previous file
 return

#----------------------------------------- Search identifier in file

#Print out lines of file "filename" that contains "searching"

def search(filename, searching, TEXTCASE, DISPLAY):
 print "Searching identifier " + searching + " in " + filename

 global counter

 f = openread(filename)   # Local function
 if not f: return
 slen = len(searching)
 linenum = 0

 while 1:
  line = f.readline()
  if not line: break
  linenum = linenum + 1
  old = counter

  words = split(line)    # local split

  for cmp in words:
    if searching == cmp:  counter = counter + 1
    else:
     if TEXTCASE == FALSE:
      if string.lower(searching) == string.lower(cmp):
        counter = counter + 1

  if counter > old:
   if DISPLAY == TRUE:
    # A trailing comma to avoid new line
    print string.rjust(str(linenum), 4), line,  

 f.close()
 return counter

#-------------------------------------  Replace identifier in file

#Replace occurence of "searching" by "replacing" in file "filename"

def replaceid(srcname, searching, replacing, TEXTCASE, DISPLAY):

 print "Replacing identifier" , searching , "by" , replacing , "in" , srcname

 #Making a temporary file for destination
 global counter
 dstname = srcname + ".tmp"
 if os.path.exists(dstname):
  try:
   os.remove(dstname)
  except:
   print "Enable to clean", dstname, "replacing cancelled"
   return 0

 src = openread(srcname)    # Local functions
 dst = openwrite(dstname)
 if (not src) | (not dst): return 0

 slen = len(searching)
 linenum = 0
 if TEXTCASE == FALSE:
  searching = string.lower(searching)

 while 1:
  line = src.readline()
  if not line: break

  found = FALSE
  dstwords = []
  srcwords = split(line)    # local split

  # Adding either same or replacing word
  for cmp in srcwords:
    word = cmp
    if searching == cmp:
      found = TRUE
      word = replacing
      counter = counter + 1
    else:
      if (TEXTCASE == FALSE) & (searching == string.lower(cmp)):
       found = TRUE
       word = replacing
    dstwords.append(word)

  linenum = linenum + 1
  line = join(dstwords)

  # Cleaning line separator
  line = string.replace(line, '\r', '')
  line = string.replace(line, '\n', '')

  dst.write(line + "\n")

  if (found == TRUE) & (DISPLAY == TRUE):
    print string.rjust(str(linenum), 4), line

 src.close()
 dst.close()

 # Now replacing the old file with the new updated one
 replacefile(srcname, dstname)
 return counter


#------------------------------  Search string in ascii text

# Search occurences of string "searching" in file "filename"

def searchstr(srcname, searching, TEXTCASE, DISPLAY):

 global counter

 print "Searching string \"" + searching + "\" in " + srcname

 src = openread(srcname)
 if not src: return

 linenum = 0
 if TEXTCASE == FALSE:
  searching = string.lower(searching)

 while 1:
  line = src.readline()
  if not line: break
  linenum = linenum + 1
  if TEXTCASE == FALSE: line = string.lower(line)

  # Locating, counting and displaying

  if string.find(line, searching) != -1:
    if DISPLAY == TRUE: print string.rjust(str(linenum), 4), line,
    counter = counter + string.count(line, searching)

 src.close()
 return counter


#-----------------------------  Replace a string in an ascii file

#Replace occurences of "searching" by "replacing" in file "filename"

def replacestr(srcname, searching, replacing, TEXTCASE, DISPLAY):

 print "Replacing string \"" + searching + "\" by \"" + replacing + "\" in " + srcname

 global counter
 #Making a temporary file for destination
 dstname = srcname + ".tmp"
 if os.path.exists(dstname):
  try:
   os.remove(dstname)
  except:
   print "Enable to clean", dstname, "replacing cancelled"
   return

 src = openread(srcname)
 dst = openwrite(dstname)
 if (not src) | (not dst): return

 slen = len(searching)
 linenum = 1
 
 while 1:
  line = src.readline()
  if not line: break

  # Removing end of line codes

  line = string.replace(line, '\r', '')
  oline = string.replace(line, '\n', '')
  oldcounter = counter

  # Replacing
  line = replace(oline, searching, replacing, TEXTCASE)  # Local replace()

  # Displaying
  if (DISPLAY == TRUE) & (counter > oldcounter):
    print string.rjust(str(linenum), 4), line

  dst.write(line + "\n")
  linenum = linenum + 1

 src.close()
 dst.close()

 # Now replacing the old file with the new updated one
 replacefile(srcname, dstname)


#---------------------------------------------------
#                   Main program
#---------------------------------------------------

def main():

 #--- Options

 # The program requires 3 parameters plus one or two optionnals
 onum = len(sys.argv)
 if (onum < 3) | (onum > 5): syntax()

 # Defaults

 global counter
 TEXTCASE = TRUE
 DISPLAY = TRUE
 filecase = TRUE
 text = TRUE
 searching = ""
 replacing = ""
 pattern = ""

 # Processing options

 optstr = sys.argv[1]
 optchr = optstr[0:1]

 if (optchr == '-') | (optchr == '/'):
  opt = sys.argv[1][1:]
  del sys.argv[1]
  onum = onum - 1
  for i in opt:
   if    i == 'i': TEXTCASE = FALSE     # Ignore case
   elif  i == 'c': text = FALSE         # Identifiers in code
   elif  i == 'w': filecase = FALSE     # Ignore case for filenames
   elif  i == 'q': DISPLAY = FALSE      # Quiet, no display of changes
   elif  i == 'v': version()
   elif  i == 'h': syntax()
   else:
    print i + " bad option"
    syntax()

 if onum == 4:
  replacing = sys.argv[2]
  del sys.argv[2]

 searching = sys.argv[1]
 pattern = sys.argv[2]

 #--- Parsing the directory

 #Directory list
 liste = os.listdir(os.getcwd())
 fctr = 0    # Total files
 match = 0   # Total selected files
 counter = 0 # Matches

 for filename in liste:
  if not os.path.isfile(filename): pass
  else:
   fctr = fctr + 1        # Total files found
   if matching(pattern, filename, filecase):
    match = match + 1     # Selected files count
    if replacing == "":
     if text == FALSE:
       search(filename, searching, TEXTCASE, DISPLAY)
     else:
       searchstr(filename, searching, TEXTCASE, DISPLAY)
    else:
     if text == FALSE:
       replaceid(filename, searching, replacing, TEXTCASE, DISPLAY)
     else:
       replacestr(filename, searching, replacing, TEXTCASE, DISPLAY)

 # Inner function that adds a "s" to names (I put to the test python's limits!)

 def plural(num): return ("","","s")[min(2, num)]

 print fctr , "file" + plural(fctr) + ",", match, "file" + plural(match) , "matching," \
     , counter , "found"
 return 0

main()

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -